nginx-testing
Version:
Support for integration/acceptance testing of nginx configuration.
240 lines • 9.69 kB
TypeScript
/// <reference types="node" />
import { Writable } from 'node:stream';
import { PatchOperation } from './nginxConf';
type ConfigPatch = Array<PatchOperation & {
ifModule?: string;
}>;
/**
* The default patch to be applied on the nginx configs to make it compatible with
* the runner.
*/
export declare const configPatch: ConfigPatch;
/**
* Options for the {@link startNginx} function.
*/
export type NginxOptions = RequiredKeys<BaseOptions, 'configPath'> | RequiredKeys<BaseOptions, 'config'>;
/**
* Options for the {@link startNginx} function.
*/
interface BaseOptions {
/**
* Name or path of the nginx binary to start. Defaults to `'nginx'`.
*
* This option is ignored if `version` is provided.
*/
binPath?: string;
/**
* A SemVer version range specifying the nginx version to run.
*
* Nginx binary for your OS and architecture will be downloaded from
* [nginx-binaries](https://github.com/jirutka/nginx-binaries). It will be stored in
* directory `.cache/nginx-binaries/` inside the nearest writable `node_modules`
* directory or in `nginx-binaries/` inside the system-preferred temp directory.
*
* Not all versions are available. You can find a list of available binaries at
* [nginx-binaries](https://jirutka.github.io/nginx-binaries/).
*/
version?: string;
/**
* Nginx configuration to use.
*
* If `configPath` is provided, the processed config will be written to a temporary
* file `.<filename>~` (where `<filename>` is a filename from `configPath`) in the
* `configPath`'s directory (e.g. `conf/nginx.conf` -> `conf/.nginx.conf~`). Otherwise
* it will be written into `nginx.conf` file in `workDir`. In either case, this file
* will be automatically deleted after stopping the nginx.
*
* The config may include the following placeholders which will be replaced with
* corresponding values:
*
* - `__ADDRESS__` -- The address as specified in `bindAddress`.
* - `__CONFDIR__` -- Path to directory with the config file as specified in `configPath`.
* - `__CWD__` -- The current working directory as reported by `process.cwd()`.
* - `__WORKDIR__` -- Path to the nginx's working directory as specified in `workDir`.
* - `__PORT__`, `__PORT_1__`, ..., `__PORT_9__` -- The port numbers as specified in
* `ports` and `preferredPorts`.
*
* It will be modified for compatibility with the runner by applying patch operations
* specified in {@link configPatch} variable.
*
* Either `configPath`, or `config` must be provided!
*/
config?: string;
/**
* Path of the nginx configuration file to use.
*
* This file will be processed and the resulting config file will be written to
* a temporary file `.<filename>~` (where `<filename>` is a filename from `configPath`)
* in the `configPath`'s directory (e.g. `conf/nginx.conf` -> `conf/.nginx.conf~`).
* This temporary file will be automatically deleted after stopping the nginx.
*
* See {@link config} option for information about placeholders and patching.
*
* Either `configPath`, or `config` must be provided!
*/
configPath?: string;
/**
* Hostname or IP address the port(s) will be binding on. This is used when searching
* for free ports (see `preferredPorts`) and for substituting `__ADDRESS__` placeholder
* in the given nginx config. Defaults to `'127.0.0.1'`.
*/
bindAddress?: string;
/**
* A list of port numbers for substituting `__PORT__`, `__PORT_1__`, ..., `__PORT_9__`
* placeholders in the given nginx config. Unlike `preferredPorts`, these are _not_
* checked for availability and nginx will fail to start if any of the provided and
* used ports is unavailable.
*
* If it's not provided or more ports are needed, next ports are selected from the
* `preferredPorts` or randomly.
*/
ports?: number[];
/**
* A list of preferred port numbers to use for substituting `__PORT__`, `__PORT_1__`,
* ..., `__PORT_9__` placeholders in the given nginx config.
*
* Unavailable ports (used by some other program or restricted by OS) are skipped.
* If there are no preferred ports left and another port is needed, a random port
* number is used.
*/
preferredPorts?: number[];
/**
* Path of a directory that will be passed as a _prefix_ (`-p`) into `nginx`.
* It will be automatically created if doesn't exist.
*
* If not provided, an unique temporary directory will be created:
* `.cache/nginx-testing-XXXXXX/` relative to the nearest writable `node_modules`
* (nearest to `process.cwd()`) or `nginx-testing-XXXXXX/` in the system-preferred
* temp directory. The created directory will be automatically deleted after stopping.
*/
workDir?: string;
/**
* One of:
*
* - `'buffer'` -- Collect the nginx's stderr to a buffer that can be read using
* `readErrorLog()` (default).
* - `'ignore'` -- Ignore nginx's stderr.
* - `'inherit'` -- Pass through the nginx's stderr output to the Node process.
* - `<Writable>` -- A writable stream to pipe the nginx's stderr to.
*
* Nginx error log is expected to be redirected to _stderr_.
* Directive `error_log stderr info;` will be automatically added to the config,
* unless there's already `error_log` defined in the main context.
*/
errorLog?: 'buffer' | 'ignore' | 'inherit' | Writable;
/**
* One of:
*
* - `'buffer'` -- Collect the nginx's access log to a buffer that can be read using
* `readAccessLog()` (default).
* - `'ignore'` -- Ignore nginx's access log.
* - `<Writable>` -- A writable stream to pipe the nginx's access log to.
*
* Nginx access log is expected to be redirected to file `<workDir>/access.log`.
* Directive `access_log access.log;` will be automatically added to the config,
* unless there's already `access_log` defined in the `http` context.
*/
accessLog?: 'buffer' | 'ignore' | Writable;
/**
* Number of milliseconds after the start to wait for the nginx to respond to the
* health-check request (`HEAD http://<bindAddress>:<ports[0]>/health`). Any HTTP
* status is considered as success - it just checks if the nginx is listening and
* responding.
*
* Defaults to `1000`.
*/
startTimeoutMsec?: number;
}
type RequiredKeys<O extends object, K extends keyof O = keyof O> = O & {
[L in K]-?: O[L];
};
/**
* A return value of the {@link startNginx} function.
*/
export interface NginxServer {
/**
* The current nginx configuration.
*/
readonly config: string;
/**
* PID of the nginx process.
*/
readonly pid: number;
/**
* Number of the first port allocated for nginx, i.e. the port on which nginx
* should listen for connections. It's the same as `ports[0]`.
*/
readonly port: number;
/**
* A list of port numbers allocated for nginx.
*/
readonly ports: ReadonlyArray<number>;
/**
* Path of the nginx's working directory.
*/
readonly workDir: string;
/**
* Reads new messages from the access log since the last call of `readAccessLog()`.
*
* @throws {Error} if the process was created with option `accessLog` other than
* `'buffer'` or `undefined`.
*/
readAccessLog(): Promise<string>;
/**
* Reads new messages from the error log since the last call of `readErrorLog()`.
*
* @throws {Error} if the process was created with option `errorLog` other than
* `'buffer'` or `undefined`.
*/
readErrorLog(): Promise<string>;
/**
* Reloads the nginx (using SIGHUP), optionally with a new configuration.
* Options `config` and `configPath` are mutually exclusive here.
*
* Nginx can be reloaded only when running with the master process. This is disabled
* by default, but you can override it by declaring `master_process on` in the config.
*
* **Important:** The function you are looking for is `restart()`. Use `reload()` only
* if you know that you cannot use `restart()`.
*
* **Cation:** This function doesn't work on Windows!
*
* @throws {Error} if nginx was started with `master_process off`.
* @throws {Error} if running on Windows (`win32` platform).
*/
reload(opts?: RestartOptions): Promise<void>;
/**
* Restarts the nginx, optionally with a new configuration.
* Options `config` and `configPath` are mutually exclusive here.
*
* The new nginx process will be started with the same ports, working directory etc.
*/
restart(opts?: RestartOptions): Promise<void>;
/**
* Stops the nginx and cleans-up temporary files and directories.
*/
stop(): Promise<void>;
}
type RestartOptions = Pick<BaseOptions, 'config' | 'configPath'>;
/**
* Starts nginx server with the given configuration.
*
* @example
* import { startNginx, NginxServer } from 'nginx-testing'
* import fetch from 'node-fetch'
*
* let nginx: NginxServer
*
* before(async () => {
* nginx = await startNginx({ version: '1.24.x', configPath: './nginx.conf' })
* })
* after(nginx.stop)
*
* test('GET / results in HTTP 200', async () => {
* const resp = await fetch(`http://localhost:${nginx.port}/`)
* assert(resp.status === 200)
* })
*/
export declare function startNginx(opts: NginxOptions): Promise<NginxServer>;
export {};
//# sourceMappingURL=nginxRunner.d.ts.map