77 *
88 */
99
10- var fs = require ( 'fs' ) ,
10+ const
11+ fs = require ( 'fs' ) . promises ,
1112 tls = require ( 'tls' ) ,
1213 path = require ( 'path' ) ,
1314 constants = require ( 'constants' ) ,
1415 connected = require ( 'connected' ) ,
1516 errs = require ( 'errs' ) ,
1617 assign = require ( 'object-assign' ) ;
1718
18- var pemFormat = / - - - - - B E G I N / ;
19+ const pemFormat = / - - - - - B E G I N / ;
1920
20- var CIPHERS = [
21+ const CIPHERS = [
2122 'ECDHE-RSA-AES256-SHA384' ,
2223 'DHE-RSA-AES256-SHA384' ,
2324 'ECDHE-RSA-AES256-SHA256' ,
@@ -36,7 +37,7 @@ var CIPHERS = [
3637 '!CAMELLIA'
3738] . join ( ':' ) ;
3839
39- var secureOptions = constants . SSL_OP_NO_SSLv3 ;
40+ const secureOptions = constants . SSL_OP_NO_SSLv3 ;
4041
4142/**
4243 * function createServers (dispatch, options, callback)
@@ -49,31 +50,28 @@ module.exports = async function createServers(options, listening) {
4950 return listening ( err ) ;
5051 }
5152
52- const [
53- [ httpErr , http ] ,
54- [ httpsErr , https ] ,
55- [ http2Err , http2 ] ] = await Promise . all ( [
53+ const [ httpResult , httpsResult , http2Result ] = await Promise . allSettled ( [
5654 createHttp ( options . http , options . log ) ,
5755 createHttps ( options . https , options . log ) ,
5856 createHttps ( options . http2 , options . log , true )
59- ] ) ;
57+ ] )
6058
6159 const servers = { } ;
62- if ( http ) servers . http = http ;
63- if ( https ) servers . https = https ;
64- if ( http2 ) servers . http2 = http2 ;
60+ if ( httpResult . value ) servers . http = httpResult . value ;
61+ if ( httpsResult . value ) servers . https = httpsResult . value ;
62+ if ( http2Result . value ) servers . http2 = http2Result . value ;
6563
66- if ( httpErr || httpsErr || http2Err ) {
67- let errorSource = http2Err || httpsErr || httpErr ;
64+ const errorSource = httpResult . reason || httpsResult . reason || http2Result . reason ;
65+ if ( errorSource ) {
6866 if ( Array . isArray ( errorSource ) ) {
6967 errorSource = errorSource [ 0 ] ;
7068 }
7169 return listening (
7270 errs . create ( {
7371 message : errorSource && errorSource . message ,
74- http2 : http2Err ,
75- https : httpsErr ,
76- http : httpErr
72+ http2 : http2Result . reason ,
73+ https : httpsResult . reason ,
74+ http : httpResult . reason
7775 } ) ,
7876 servers
7977 ) ;
@@ -172,25 +170,25 @@ function normalizeCertChainList(root, data) {
172170 // If this is an array, treat like an array of bundles, otherwise a single
173171 // bundle
174172 return Array . isArray ( data )
175- ? data . map ( function ( item ) {
173+ ? Promise . all ( data . map ( function ( item ) {
176174 return normalizeCertChain ( root , item ) ;
177- } )
175+ } ) )
178176 : normalizePEMContent ( root , data ) ;
179177}
180178
181- function normalizeCertChain ( root , data ) {
179+ async function normalizeCertChain ( root , data ) {
182180 // A chain can be an array, which we concatenate together into one PEM,
183181 // an already-concatenated chain, or a single PEM
184182
185- const content = normalizePEMContent ( root , data ) ;
183+ const content = await normalizePEMContent ( root , data ) ;
186184 return Array . isArray ( content ) ? content . join ( '\n' ) : content ;
187185}
188186
189187function normalizeCA ( root , ca ) {
190188 if ( ca && ! Array . isArray ( ca ) ) {
191189 ca = [ ca ] ;
192190 }
193- return ca && ca . map ( normalizePEMContent . bind ( null , root ) ) ;
191+ return ca && Promise . all ( ca . map ( normalizePEMContent . bind ( null , root ) ) ) ;
194192}
195193
196194/**
@@ -201,9 +199,9 @@ function normalizeCA(root, ca) {
201199 */
202200function normalizePEMContent ( root , file ) {
203201 if ( Array . isArray ( file ) )
204- return file . map ( function map ( item ) {
202+ return Promise . all ( file . map ( function map ( item ) {
205203 return normalizePEMContent ( root , item ) ;
206- } ) ;
204+ } ) ) ;
207205
208206 //
209207 // Assumption that this is a Buffer, a PEM file, or something broken
@@ -212,7 +210,7 @@ function normalizePEMContent(root, file) {
212210 return file ;
213211 }
214212
215- return fs . readFileSync ( path . resolve ( root , file ) ) ;
213+ return fs . readFile ( path . resolve ( root , file ) ) ;
216214}
217215
218216function normalizeCiphers ( ciphers ) {
@@ -226,11 +224,11 @@ function normalizeCiphers(ciphers) {
226224 return ciphers ;
227225}
228226
229- function getSNIHandler ( sslOpts ) {
230- var sniHosts = Object . keys ( sslOpts . sni ) ;
227+ async function getSNIHandler ( sslOpts ) {
228+ const sniHosts = Object . keys ( sslOpts . sni ) ;
231229
232230 // Pre-compile regexps for the hostname
233- var hostRegexps = sniHosts . map ( function ( host ) {
231+ const hostRegexps = sniHosts . map ( function ( host ) {
234232 return host === '*' ? / .* / : new RegExp (
235233 '^' +
236234 host
@@ -242,16 +240,22 @@ function getSNIHandler(sslOpts) {
242240 } ) ;
243241
244242 // Prepare secure contexts ahead-of-time
245- var hostSecureContexts = sniHosts . map ( function ( host ) {
243+ const hostSecureContexts = await Promise . all ( sniHosts . map ( async function ( host ) {
246244 var hostOpts = sslOpts . sni [ host ] ;
247245
248246 var root = hostOpts . root || sslOpts . root ;
249247
248+ const [ key , cert , ca ] = await Promise . all ( [
249+ normalizePEMContent ( root , hostOpts . key ) ,
250+ normalizeCertContent ( root , hostOpts . cert ) ,
251+ normalizeCA ( root , hostOpts . ca || sslOpts . ca )
252+ ] )
253+
250254 return tls . createSecureContext (
251255 assign ( { } , sslOpts , hostOpts , {
252- key : normalizePEMContent ( root , hostOpts . key ) ,
253- cert : normalizeCertContent ( root , hostOpts . cert ) ,
254- ca : normalizeCA ( root , hostOpts . ca || sslOpts . ca ) ,
256+ key,
257+ cert,
258+ ca,
255259 ciphers : normalizeCiphers ( hostOpts . ciphers || sslOpts . ciphers ) ,
256260 honorCipherOrder : ! ! (
257261 hostOpts . honorCipherOrder || sslOpts . honorCipherOrder
@@ -260,7 +264,7 @@ function getSNIHandler(sslOpts) {
260264 secureOptions : secureOptions
261265 } )
262266 ) ;
263- } ) ;
267+ } ) ) ;
264268
265269 return function ( hostname , cb ) {
266270 var matchingHostIdx = sniHosts . findIndex ( function ( candidate , i ) {
@@ -282,29 +286,30 @@ function getSNIHandler(sslOpts) {
282286async function createHttp ( httpConfig , log ) {
283287 if ( typeof httpConfig === 'undefined' ) {
284288 log ( 'http | no options.http; no server' ) ;
285- return [ null , null ] ;
289+ return null ;
286290 }
287291
288292 if ( Array . isArray ( httpConfig ) ) {
289293 return await createMultiple ( createHttp , httpConfig , log ) ;
290294 }
291295
292- return await new Promise ( resolve => {
293- var server = require ( 'http' ) . createServer ( httpConfig . handler ) ,
294- timeout = httpConfig . timeout ,
295- port = httpConfig . port ,
296- args ;
296+ const
297+ server = require ( 'http' ) . createServer ( httpConfig . handler ) ,
298+ timeout = httpConfig . timeout ,
299+ port = httpConfig . port ;
297300
298- if ( typeof timeout === 'number' ) server . setTimeout ( timeout ) ;
301+ if ( typeof timeout === 'number' ) server . setTimeout ( timeout ) ;
299302
300- args = [ server , port ] ;
301- if ( httpConfig . host ) {
302- args . push ( httpConfig . host ) ;
303- }
303+ const args = [ server , port ] ;
304+ if ( httpConfig . host ) {
305+ args . push ( httpConfig . host ) ;
306+ }
307+
308+ log ( 'http | try listen ' + port ) ;
304309
305- log ( 'http | try listen ' + port ) ;
310+ return new Promise ( ( resolve , reject ) => {
306311 args . push ( function listener ( err ) {
307- resolve ( [ err , server ] ) ;
312+ err ? reject ( err ) : resolve ( server ) ;
308313 } ) ;
309314 connected . apply ( null , args ) ;
310315 } ) ;
@@ -317,73 +322,76 @@ async function createHttp(httpConfig, log) {
317322async function createHttps ( ssl , log , h2 ) {
318323 if ( typeof ssl === 'undefined' ) {
319324 log ( 'https | no options.https; no server' ) ;
320- return [ null , null ] ;
325+ return null ;
321326 }
322327
323328 if ( Array . isArray ( ssl ) ) {
324329 return await createMultiple ( createHttps , ssl , log , h2 ) ;
325330 }
326331
327- return await new Promise ( resolve => {
328- var port = ssl . port ,
329- timeout = ssl . timeout ,
330- server ,
331- args ;
332-
333- var finalHttpsOptions = assign ( { } , ssl , {
334- //
335- // Load default SSL key, cert and ca(s).
336- //
337- key : normalizePEMContent ( ssl . root , ssl . key ) ,
338- cert : normalizeCertContent ( ssl . root , ssl . cert , ssl . key ) ,
339- ca : normalizeCA ( ssl . root , ssl . ca ) ,
340- //
341- // Properly expose ciphers for an A+ SSL rating:
342- // https://certsimple.com/blog/a-plus-node-js-ssl
343- //
344- ciphers : normalizeCiphers ( ssl . ciphers ) ,
345- honorCipherOrder : ! ! ssl . honorCipherOrder ,
346- //
347- // Protect against the POODLE attack by disabling SSLv3
348- // @see http://googleonlinesecurity.blogspot.nl/2014/10/this-poodle-bites-exploiting-ssl-30.html
349- //
350- secureProtocol : 'SSLv23_method' ,
351- secureOptions : secureOptions
352- } ) ;
332+ const [ key , cert , ca ] = await Promise . all ( [
333+ normalizePEMContent ( ssl . root , ssl . key ) ,
334+ normalizeCertContent ( ssl . root , ssl . cert , ssl . key ) ,
335+ normalizeCA ( ssl . root , ssl . ca )
336+ ] ) ;
353337
354- if ( ssl . sni && ! finalHttpsOptions . SNICallback ) {
355- finalHttpsOptions . SNICallback = getSNIHandler ( ssl ) ;
356- }
338+ const finalHttpsOptions = assign ( { } , ssl , {
339+ key,
340+ cert,
341+ ca,
342+ //
343+ // Properly expose ciphers for an A+ SSL rating:
344+ // https://certsimple.com/blog/a-plus-node-js-ssl
345+ //
346+ ciphers : normalizeCiphers ( ssl . ciphers ) ,
347+ honorCipherOrder : ! ! ssl . honorCipherOrder ,
348+ //
349+ // Protect against the POODLE attack by disabling SSLv3
350+ // @see http://googleonlinesecurity.blogspot.nl/2014/10/this-poodle-bites-exploiting-ssl-30.html
351+ //
352+ secureProtocol : 'SSLv23_method' ,
353+ secureOptions : secureOptions
354+ } ) ;
357355
358- log ( 'https | listening on %d' , port ) ;
359- if ( h2 ) {
360- server = require ( 'http2' ) . createSecureServer ( finalHttpsOptions , ssl . handler )
361- } else {
362- server = require ( 'https' ) . createServer ( finalHttpsOptions , ssl . handler ) ;
363- }
356+ if ( ssl . sni && ! finalHttpsOptions . SNICallback ) {
357+ finalHttpsOptions . SNICallback = await getSNIHandler ( ssl ) ;
358+ }
364359
365- if ( typeof timeout === 'number' ) server . setTimeout ( timeout ) ;
366- args = [ server , port ] ;
367- if ( ssl . host ) {
368- args . push ( ssl . host ) ;
369- }
360+ const port = ssl . port ;
361+ log ( 'https | listening on %d' , port ) ;
362+ const server = h2
363+ ? require ( 'http2' ) . createSecureServer ( finalHttpsOptions , ssl . handler )
364+ : require ( 'https' ) . createServer ( finalHttpsOptions , ssl . handler ) ;
365+
366+ const timeout = ssl . timeout ;
367+ if ( typeof timeout === 'number' ) server . setTimeout ( timeout ) ;
368+ const args = [ server , port ] ;
369+ if ( ssl . host ) {
370+ args . push ( ssl . host ) ;
371+ }
370372
373+ return new Promise ( ( resolve , reject ) => {
371374 args . push ( function listener ( err ) {
372- resolve ( [ err , server ] ) ;
375+ err ? reject ( err ) : resolve ( server ) ;
373376 } ) ;
374377 connected . apply ( null , args ) ;
375378 } ) ;
376379}
377380
378381async function createMultiple ( createFn , configArray , log ) {
379- const errorsOrServers = await Promise . all (
382+ const errorsOrServers = await Promise . allSettled (
380383 configArray . map ( cfg => createFn ( cfg , log ) )
381384 ) ;
382- const errors = [ ] ,
383- servers = [ ] ;
384- for ( const [ error , server ] of errorsOrServers ) {
385- error && errors . push ( error ) ;
386- server && servers . push ( server ) ;
385+
386+ const errors = [ ] , servers = [ ] ;
387+ for ( const result of errorsOrServers ) {
388+ result . reason && errors . push ( result . reason ) ;
389+ result . value && servers . push ( result . value ) ;
390+ }
391+
392+ if ( errors . length ) {
393+ throw errors ;
394+ } else {
395+ return servers ;
387396 }
388- return [ errors . length ? errors : null , servers ] ;
389397}
0 commit comments