Skip to content

Commit

Permalink
feat: add debugPort to allow listen both https and http protocol (#109)
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 committed Jun 27, 2023
1 parent 03a7854 commit 74cbb35
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 7 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ startCluster(options, () => {
| workers | `Number` | numbers of app workers |
| sticky | `Boolean` | sticky mode server |
| port | `Number` | port |
| debugPort | `Number` | the debug port only listen on http protocol |
| https | `Object` | start a https server, note: `key` / `cert` / `ca` should be full path to file |
| require | `Array\|String` | will inject into worker/agent process |
| pidFile | `String` | will save master pid to this file |
Expand Down
12 changes: 12 additions & 0 deletions lib/app_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const clusterConfig = app.config.cluster || /* istanbul ignore next */ {};
const listenConfig = clusterConfig.listen || /* istanbul ignore next */ {};
const httpsOptions = Object.assign({}, clusterConfig.https, options.https);
const port = options.port = options.port || listenConfig.port;
const debugPort = options.debugPort;
const protocol = (httpsOptions.key && httpsOptions.cert) ? 'https' : 'http';

AppWorker.send({
Expand Down Expand Up @@ -72,15 +73,22 @@ function startServer(err) {
app.removeListener('startTimeout', startTimeoutHandler);

let server;
let debugPortServer;

// https config
if (httpsOptions.key && httpsOptions.cert) {
httpsOptions.key = fs.readFileSync(httpsOptions.key);
httpsOptions.cert = fs.readFileSync(httpsOptions.cert);
httpsOptions.ca = httpsOptions.ca && fs.readFileSync(httpsOptions.ca);
server = require('https').createServer(httpsOptions, app.callback());
if (debugPort) {
debugPortServer = require('http').createServer(app.callback());
}
} else {
server = require('http').createServer(app.callback());
if (debugPort) {
debugPortServer = server;
}
}

server.once('error', err => {
Expand Down Expand Up @@ -118,6 +126,10 @@ function startServer(err) {
debug('listen options %s', args);
server.listen(...args);
}
if (debugPortServer) {
debug('listen on debug port: %s', debugPort);
debugPortServer.listen(debugPort);
}
}

AppWorker.send({
Expand Down
11 changes: 10 additions & 1 deletion lib/master.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const ready = require('get-ready');
const GetFreePort = require('detect-port');
const ConsoleLogger = require('egg-logger').EggConsoleLogger;
const utility = require('utility');
const terminalLink = require('terminal-link');

const Manager = require('./utils/manager');
const parseOptions = require('./utils/options');
Expand All @@ -33,6 +34,7 @@ class Master extends EventEmitter {
* - {Object} [plugins] - customized plugins, for unittest
* - {Number} [workers] numbers of app workers, default to `os.cpus().length`
* - {Number} [port] listening port, default to 7001(http) or 8443(https)
* - {Number} [debugPort] listening a debug port on http protocol
* - {Object} [https] https options, { key, cert, ca }, full path
* - {Array|String} [require] will inject into worker/agent process
* - {String} [pidFile] will save master pid to this file
Expand Down Expand Up @@ -91,15 +93,22 @@ class Master extends EventEmitter {
this.ready(() => {
this.isStarted = true;
const stickyMsg = this.options.sticky ? ' with STICKY MODE!' : '';
const startedURL = terminalLink(this[APP_ADDRESS], this[APP_ADDRESS], { fallback: false });
this.logger.info('[master] %s started on %s (%sms)%s',
frameworkPkg.name, this[APP_ADDRESS], Date.now() - startTime, stickyMsg);
frameworkPkg.name, startedURL, Date.now() - startTime, stickyMsg);
if (this.options.debugPort) {
const url = getAddress({ port: this.options.debugPort, protocol: 'http' });
const debugPortURL = terminalLink(url, url, { fallback: false });
this.logger.info('[master] %s started on %s', frameworkPkg.name, debugPortURL);
}

const action = 'egg-ready';
this.messenger.send({
action,
to: 'parent',
data: {
port: this[REAL_PORT],
debugPort: this.options.debugPort,
address: this[APP_ADDRESS],
protocol: this[PROTOCOL],
},
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"ps-tree": "^1.2.0",
"semver": "^5.6.0",
"sendmessage": "^1.1.0",
"terminal-link": "^2.1.1",
"utility": "^1.15.0"
},
"devDependencies": {
Expand All @@ -57,7 +58,8 @@
"pedding": "^1.1.0",
"supertest": "^4.0.0",
"ts-node": "^10.9.1",
"typescript": "^5.0.4"
"typescript": "^5.0.4",
"urllib": "^3.17.1"
},
"engines": {
"node": ">= 14.0.0"
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/apps/agent-die-on-forkapp/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ module.exports = function(app) {
process.send({
action: 'kill-agent',
});
setTimeout(app.readyCallback(), 2000);
setTimeout(app.readyCallback('kill-agent-callback'), 2000);
};
35 changes: 31 additions & 4 deletions test/https.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ const mm = require('egg-mock');
const urllib = require('urllib');
const utils = require('./utils');

const httpclient = new urllib.HttpClient({ connect: { rejectUnauthorized: false } });

describe('test/https.test.js', () => {
let app;

afterEach(mm.restore);

describe('start https server with cluster options', () => {
afterEach(() => app && app.close());

it('should success with status 200', async () => {

const baseDir = path.join(__dirname, 'fixtures/apps/https-server');
const options = {
baseDir,
Expand All @@ -27,7 +27,7 @@ describe('test/https.test.js', () => {
app = utils.cluster('apps/https-server', options);
await app.ready();

const response = await urllib.request('https://127.0.0.1:8443', {
const response = await httpclient.request('https://127.0.0.1:8443', {
dataType: 'text',
rejectUnauthorized: false,
});
Expand All @@ -36,6 +36,33 @@ describe('test/https.test.js', () => {
assert(response.data === 'https server');
});

it('should listen https and http at the same time', async () => {
const baseDir = path.join(__dirname, 'fixtures/apps/https-server');
const options = {
baseDir,
debugPort: 7001,
port: 8443,
https: {
key: utils.getFilepath('server.key'),
cert: utils.getFilepath('server.cert'),
ca: utils.getFilepath('server.ca'),
},
};
app = utils.cluster('apps/https-server', options);
await app.ready();

let response = await httpclient.request('https://127.0.0.1:8443', {
dataType: 'text',
});
assert(response.status === 200);
assert(response.data === 'https server');

response = await httpclient.request('http://127.0.0.1:7001', {
dataType: 'text',
});
assert(response.status === 200);
assert(response.data === 'https server');
});
});

describe('start https server with app config cluster', () => {
Expand All @@ -51,7 +78,7 @@ describe('test/https.test.js', () => {
app = utils.cluster('apps/https-server-config', options);
await app.ready();

const response = await urllib.request('https://127.0.0.1:8443', {
const response = await httpclient.request('https://127.0.0.1:8443', {
dataType: 'text',
rejectUnauthorized: false,
});
Expand Down

0 comments on commit 74cbb35

Please sign in to comment.