nginx-testing
Version:
Support for integration/acceptance testing of nginx configuration.
147 lines (135 loc) • 5.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const process = require("node:process");
const node_watch_1 = require("node-watch");
const parseArgs = require("minimist");
const utils_1 = require("./internal/utils");
const logger_1 = require("./logger");
const nginxRunner_1 = require("./nginxRunner");
const { version: pkgVersion, bugs: bugsUrl } = require('../package.json');
// TODO: Allow to set log level.
const progName = 'start-nginx';
// NOTE: Keep in sync with CLI section in README.adoc (until I write a script to generate it).
const helpMsg = `\
Usage:
${progName} [options] <conf-file>
${progName} -h | --help
Start nginx server with the given config and reload it on changes.
This program is part of nginx-testing ${pkgVersion}.
Arguments:
<conf-file> Path of the nginx configuration file.
Options:
-b --bin-path <file> Name or path of the nginx binary to start. Defaults to 'nginx'.
This option is ignored if --version is specified.
-v --version <semver> A SemVer version range specifying the nginx version to download from
nginx-binaries a and run.
-A --bind-address <host> Hostname or IP address to bind the port(s) on. Defaults to 127.0.0.1.
-p --port <port> Port number(s) for substituting __PORT__, __PORT_1__, ..., __PORT_9__
placeholders in the nginx config. Repeat this option for more ports.
Defaults to random port numbers.
-d --work-dir <dir> Path of a directory that will be passed as a prefix into nginx.
If not provided, a temporary directory will be automatically created.
-T --start-timeout <msec> Number of milliseconds after the start to wait for the nginx to
respond to the health-check request. Defaults to 1,000 ms.
-w --watch <path> Watch file or directory (recursively) and reload nginx on changes.
<conf-file> is watched implicitly. Repeat this option for more paths.
-D --watch-delay <msec> Delay time between reloads in milliseconds. Defaults to 200 ms.
-h --help Show this message and exit.
Please report bugs at <${bugsUrl}>.
`;
const string = (value) => Array.isArray(value) ? String(value[value.length - 1])
: value != null ? String(value)
: undefined;
const number = (value) => value ? parseInt(string(value)) : undefined;
function parseCliArgs(argv) {
const booleanOpts = {
'help': 'h',
};
const stringOpts = {
'bind-address': 'A',
'bin-path': 'b',
'port': 'p',
'start-timeout': 'T',
'version': 'v',
'watch': 'w',
'watch-delay': 'D',
'work-dir': 'd',
};
const args = parseArgs(argv, {
boolean: Object.keys(booleanOpts),
string: Object.keys(stringOpts),
alias: { ...booleanOpts, ...stringOpts },
stopEarly: true,
unknown: (arg) => {
if (arg.startsWith('-')) {
console.error(`Unknown option: ${arg}`);
return false;
}
else {
return true;
}
},
});
if (args.help) {
console.log(helpMsg);
return process.exit(0);
}
if (args._.length !== 1) {
console.error('Invalid number of arguments\n');
console.error(helpMsg);
return process.exit(2);
}
return {
bindAddress: string(args['bind-address']),
binPath: string(args['bin-path']),
configPath: args._[0],
ports: (0, utils_1.arrify)(args['port']).map(n => parseInt(n)),
startTimeoutMsec: number(args['start-timeout']),
version: string(args['version']),
watchPaths: (0, utils_1.arrify)(args['watch']),
watchDelay: number(args['watch-delay']),
workDir: string(args['work-dir']),
};
}
async function run(opts) {
// Reload with SIGHUP doesn't work without master process.
nginxRunner_1.configPatch.splice(nginxRunner_1.configPatch.findIndex(p => p.path === '/master_process'), 1);
const nginx = await (0, nginxRunner_1.startNginx)({
...opts,
accessLog: process.stdout,
errorLog: 'inherit',
});
logger_1.log.info('Nginx has been started, press Ctrl+C to terminate it');
const watcher = (0, node_watch_1.default)([...opts.watchPaths, opts.configPath], { delay: opts.watchDelay || 200 }, async () => nginx.reload({ configPath: opts.configPath }));
let stopping = false;
const handleSignal = async () => {
logger_1.log.info('Terminating...');
stopping = true;
watcher.close();
return await nginx.stop();
};
process.on('SIGINT', handleSignal);
process.on('SIGTERM', handleSignal);
const loop = () => {
try {
process.kill(nginx.pid, 0); // check if running
setTimeout(loop, 100);
}
catch (_a) {
if (!stopping) {
logger_1.log.error('Nginx process has died');
watcher.close();
return nginx.stop();
}
}
return;
};
loop();
}
const opts = parseCliArgs(process.argv.slice(2));
run(opts).catch(err => {
logger_1.log.error(err.message);
logger_1.log.debug(err.stack);
process.exit(1);
});
//# sourceMappingURL=nginxRunnerCli.js.map