From 84eb4d64a82f8cf01e8f178f119f8f271c447ebd Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Wed, 15 May 2019 06:44:48 +0100 Subject: [PATCH] refactor(server): clean up lib/server.js --- lib/Server.js | 233 ++++++++++++++++++++++++++------------------------ 1 file changed, 119 insertions(+), 114 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index ef4bd2a5f4..92f3db14a8 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -63,17 +63,6 @@ if (semver.satisfies(process.version, '8.6.0 - 9')) { } class Server { - static get DEFAULT_STATS() { - return { - all: false, - hash: true, - assets: true, - warnings: true, - errors: true, - errorDetails: false, - }; - } - constructor(compiler, options = {}, _log) { if (options.lazy && !options.filename) { throw new Error("'filename' option must be set in lazy mode."); @@ -142,108 +131,8 @@ class Server { this.websocketProxies = []; this.setupFeatures(); - - // if the user enables http2, we can safely enable https - if (this.options.http2 && !this.options.https) { - this.options.https = true; - } - - if (this.options.https) { - // for keep supporting CLI parameters - if (typeof this.options.https === 'boolean') { - this.options.https = { - ca: this.options.ca, - pfx: this.options.pfx, - key: this.options.key, - cert: this.options.cert, - passphrase: this.options.pfxPassphrase, - requestCert: this.options.requestCert || false, - }; - } - - for (const property of ['ca', 'pfx', 'key', 'cert']) { - const value = this.options.https[property]; - const isBuffer = value instanceof Buffer; - - if (value && !isBuffer) { - let stats = null; - - try { - stats = fs.lstatSync(fs.realpathSync(value)).isFile(); - } catch (error) { - // ignore error - } - - if (stats) { - // It is file - this.options.https[property] = fs.readFileSync(path.resolve(value)); - } else { - this.options.https[property] = value; - } - } - } - - let fakeCert; - - if (!this.options.https.key || !this.options.https.cert) { - fakeCert = getCertificate(this.log); - } - - this.options.https.key = this.options.https.key || fakeCert; - this.options.https.cert = this.options.https.cert || fakeCert; - - // Only prevent HTTP/2 if http2 is explicitly set to false - const isHttp2 = this.options.http2 !== false; - - // note that options.spdy never existed. The user was able - // to set options.https.spdy before, though it was not in the - // docs. Keep options.https.spdy if the user sets it for - // backwards compatability, but log a deprecation warning. - if (this.options.https.spdy) { - // for backwards compatability: if options.https.spdy was passed in before, - // it was not altered in any way - this.log.warn( - 'Providing custom spdy server options is deprecated and will be removed in the next major version.' - ); - } else { - // if the normal https server gets this option, it will not affect it. - this.options.https.spdy = { - protocols: ['h2', 'http/1.1'], - }; - } - - // `spdy` is effectively unmaintained, and as a consequence of an - // implementation that extensively relies on Node’s non-public APIs, broken - // on Node 10 and above. In those cases, only https will be used for now. - // Once express supports Node's built-in HTTP/2 support, migrating over to - // that should be the best way to go. - // The relevant issues are: - // - https://github.com/nodejs/node/issues/21665 - // - https://github.com/webpack/webpack-dev-server/issues/1449 - // - https://github.com/expressjs/express/issues/3388 - if (semver.gte(process.version, '10.0.0') || !isHttp2) { - if (this.options.http2) { - // the user explicitly requested http2 but is not getting it because - // of the node version. - this.log.warn( - 'HTTP/2 is currently unsupported for Node 10.0.0 and above, but will be supported once Express supports it' - ); - } - this.listeningApp = https.createServer(this.options.https, this.app); - } else { - /* eslint-disable global-require */ - // The relevant issues are: - // https://github.com/spdy-http2/node-spdy/issues/350 - // https://github.com/webpack/webpack-dev-server/issues/1592 - this.listeningApp = require('spdy').createServer( - this.options.https, - this.app - ); - /* eslint-enable global-require */ - } - } else { - this.listeningApp = http.createServer(this.app); - } + this.setupHttps(); + this.createServer(); killable(this.listeningApp); @@ -625,6 +514,122 @@ class Server { }); } + setupHttps() { + // if the user enables http2, we can safely enable https + if (this.options.http2 && !this.options.https) { + this.options.https = true; + } + + if (this.options.https) { + // for keep supporting CLI parameters + if (typeof this.options.https === 'boolean') { + this.options.https = { + ca: this.options.ca, + pfx: this.options.pfx, + key: this.options.key, + cert: this.options.cert, + passphrase: this.options.pfxPassphrase, + requestCert: this.options.requestCert || false, + }; + } + + for (const property of ['ca', 'pfx', 'key', 'cert']) { + const value = this.options.https[property]; + const isBuffer = value instanceof Buffer; + + if (value && !isBuffer) { + let stats = null; + + try { + stats = fs.lstatSync(fs.realpathSync(value)).isFile(); + } catch (error) { + // ignore error + } + + // It is file + this.options.https[property] = stats + ? fs.readFileSync(path.resolve(value)) + : value; + } + } + + let fakeCert; + + if (!this.options.https.key || !this.options.https.cert) { + fakeCert = getCertificate(this.log); + } + + this.options.https.key = this.options.https.key || fakeCert; + this.options.https.cert = this.options.https.cert || fakeCert; + + // note that options.spdy never existed. The user was able + // to set options.https.spdy before, though it was not in the + // docs. Keep options.https.spdy if the user sets it for + // backwards compatibility, but log a deprecation warning. + if (this.options.https.spdy) { + // for backwards compatibility: if options.https.spdy was passed in before, + // it was not altered in any way + this.log.warn( + 'Providing custom spdy server options is deprecated and will be removed in the next major version.' + ); + } else { + // if the normal https server gets this option, it will not affect it. + this.options.https.spdy = { + protocols: ['h2', 'http/1.1'], + }; + } + } + } + + createServer() { + if (this.options.https) { + // Only prevent HTTP/2 if http2 is explicitly set to false + const isHttp2 = this.options.http2 !== false; + + // `spdy` is effectively unmaintained, and as a consequence of an + // implementation that extensively relies on Node’s non-public APIs, broken + // on Node 10 and above. In those cases, only https will be used for now. + // Once express supports Node's built-in HTTP/2 support, migrating over to + // that should be the best way to go. + // The relevant issues are: + // - https://github.com/nodejs/node/issues/21665 + // - https://github.com/webpack/webpack-dev-server/issues/1449 + // - https://github.com/expressjs/express/issues/3388 + if (semver.gte(process.version, '10.0.0') || !isHttp2) { + if (this.options.http2) { + // the user explicitly requested http2 but is not getting it because + // of the node version. + this.log.warn( + 'HTTP/2 is currently unsupported for Node 10.0.0 and above, but will be supported once Express supports it' + ); + } + this.listeningApp = https.createServer(this.options.https, this.app); + } else { + // The relevant issues are: + // https://github.com/spdy-http2/node-spdy/issues/350 + // https://github.com/webpack/webpack-dev-server/issues/1592 + // eslint-disable-next-line global-require + this.listeningApp = require('spdy').createServer( + this.options.https, + this.app + ); + } + } else { + this.listeningApp = http.createServer(this.app); + } + } + + static get DEFAULT_STATS() { + return { + all: false, + hash: true, + assets: true, + warnings: true, + errors: true, + errorDetails: false, + }; + } + getStats(statsObj) { const stats = Server.DEFAULT_STATS; @@ -693,7 +698,7 @@ class Server { if (ip.isV4Format(hostname) || ip.isV6Format(hostname)) { return true; } - // always allow localhost host, for convience + // always allow localhost host, for convenience if (hostname === 'localhost') { return true; }