7
7
*
8
8
*/
9
9
10
- var fs = require ( 'fs' ) ,
10
+ const
11
+ fs = require ( 'fs' ) . promises ,
11
12
tls = require ( 'tls' ) ,
12
13
path = require ( 'path' ) ,
13
14
constants = require ( 'constants' ) ,
14
15
connected = require ( 'connected' ) ,
15
16
errs = require ( 'errs' ) ,
16
17
assign = require ( 'object-assign' ) ;
17
18
18
- var pemFormat = / - - - - - B E G I N / ;
19
+ const pemFormat = / - - - - - B E G I N / ;
19
20
20
- var CIPHERS = [
21
+ const CIPHERS = [
21
22
'ECDHE-RSA-AES256-SHA384' ,
22
23
'DHE-RSA-AES256-SHA384' ,
23
24
'ECDHE-RSA-AES256-SHA256' ,
@@ -36,7 +37,7 @@ var CIPHERS = [
36
37
'!CAMELLIA'
37
38
] . join ( ':' ) ;
38
39
39
- var secureOptions = constants . SSL_OP_NO_SSLv3 ;
40
+ const secureOptions = constants . SSL_OP_NO_SSLv3 ;
40
41
41
42
/**
42
43
* function createServers (dispatch, options, callback)
@@ -49,31 +50,28 @@ module.exports = async function createServers(options, listening) {
49
50
return listening ( err ) ;
50
51
}
51
52
52
- const [
53
- [ httpErr , http ] ,
54
- [ httpsErr , https ] ,
55
- [ http2Err , http2 ] ] = await Promise . all ( [
53
+ const [ httpResult , httpsResult , http2Result ] = await Promise . allSettled ( [
56
54
createHttp ( options . http , options . log ) ,
57
55
createHttps ( options . https , options . log ) ,
58
56
createHttps ( options . http2 , options . log , true )
59
- ] ) ;
57
+ ] )
60
58
61
59
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 ;
65
63
66
- if ( httpErr || httpsErr || http2Err ) {
67
- let errorSource = http2Err || httpsErr || httpErr ;
64
+ const errorSource = httpResult . reason || httpsResult . reason || http2Result . reason ;
65
+ if ( errorSource ) {
68
66
if ( Array . isArray ( errorSource ) ) {
69
67
errorSource = errorSource [ 0 ] ;
70
68
}
71
69
return listening (
72
70
errs . create ( {
73
71
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
77
75
} ) ,
78
76
servers
79
77
) ;
@@ -172,25 +170,25 @@ function normalizeCertChainList(root, data) {
172
170
// If this is an array, treat like an array of bundles, otherwise a single
173
171
// bundle
174
172
return Array . isArray ( data )
175
- ? data . map ( function ( item ) {
173
+ ? Promise . all ( data . map ( function ( item ) {
176
174
return normalizeCertChain ( root , item ) ;
177
- } )
175
+ } ) )
178
176
: normalizePEMContent ( root , data ) ;
179
177
}
180
178
181
- function normalizeCertChain ( root , data ) {
179
+ async function normalizeCertChain ( root , data ) {
182
180
// A chain can be an array, which we concatenate together into one PEM,
183
181
// an already-concatenated chain, or a single PEM
184
182
185
- const content = normalizePEMContent ( root , data ) ;
183
+ const content = await normalizePEMContent ( root , data ) ;
186
184
return Array . isArray ( content ) ? content . join ( '\n' ) : content ;
187
185
}
188
186
189
187
function normalizeCA ( root , ca ) {
190
188
if ( ca && ! Array . isArray ( ca ) ) {
191
189
ca = [ ca ] ;
192
190
}
193
- return ca && ca . map ( normalizePEMContent . bind ( null , root ) ) ;
191
+ return ca && Promise . all ( ca . map ( normalizePEMContent . bind ( null , root ) ) ) ;
194
192
}
195
193
196
194
/**
@@ -201,9 +199,9 @@ function normalizeCA(root, ca) {
201
199
*/
202
200
function normalizePEMContent ( root , file ) {
203
201
if ( Array . isArray ( file ) )
204
- return file . map ( function map ( item ) {
202
+ return Promise . all ( file . map ( function map ( item ) {
205
203
return normalizePEMContent ( root , item ) ;
206
- } ) ;
204
+ } ) ) ;
207
205
208
206
//
209
207
// Assumption that this is a Buffer, a PEM file, or something broken
@@ -212,7 +210,7 @@ function normalizePEMContent(root, file) {
212
210
return file ;
213
211
}
214
212
215
- return fs . readFileSync ( path . resolve ( root , file ) ) ;
213
+ return fs . readFile ( path . resolve ( root , file ) ) ;
216
214
}
217
215
218
216
function normalizeCiphers ( ciphers ) {
@@ -226,11 +224,11 @@ function normalizeCiphers(ciphers) {
226
224
return ciphers ;
227
225
}
228
226
229
- function getSNIHandler ( sslOpts ) {
230
- var sniHosts = Object . keys ( sslOpts . sni ) ;
227
+ async function getSNIHandler ( sslOpts ) {
228
+ const sniHosts = Object . keys ( sslOpts . sni ) ;
231
229
232
230
// Pre-compile regexps for the hostname
233
- var hostRegexps = sniHosts . map ( function ( host ) {
231
+ const hostRegexps = sniHosts . map ( function ( host ) {
234
232
return host === '*' ? / .* / : new RegExp (
235
233
'^' +
236
234
host
@@ -242,16 +240,22 @@ function getSNIHandler(sslOpts) {
242
240
} ) ;
243
241
244
242
// Prepare secure contexts ahead-of-time
245
- var hostSecureContexts = sniHosts . map ( function ( host ) {
243
+ const hostSecureContexts = await Promise . all ( sniHosts . map ( async function ( host ) {
246
244
var hostOpts = sslOpts . sni [ host ] ;
247
245
248
246
var root = hostOpts . root || sslOpts . root ;
249
247
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
+
250
254
return tls . createSecureContext (
251
255
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,
255
259
ciphers : normalizeCiphers ( hostOpts . ciphers || sslOpts . ciphers ) ,
256
260
honorCipherOrder : ! ! (
257
261
hostOpts . honorCipherOrder || sslOpts . honorCipherOrder
@@ -260,7 +264,7 @@ function getSNIHandler(sslOpts) {
260
264
secureOptions : secureOptions
261
265
} )
262
266
) ;
263
- } ) ;
267
+ } ) ) ;
264
268
265
269
return function ( hostname , cb ) {
266
270
var matchingHostIdx = sniHosts . findIndex ( function ( candidate , i ) {
@@ -282,29 +286,30 @@ function getSNIHandler(sslOpts) {
282
286
async function createHttp ( httpConfig , log ) {
283
287
if ( typeof httpConfig === 'undefined' ) {
284
288
log ( 'http | no options.http; no server' ) ;
285
- return [ null , null ] ;
289
+ return null ;
286
290
}
287
291
288
292
if ( Array . isArray ( httpConfig ) ) {
289
293
return await createMultiple ( createHttp , httpConfig , log ) ;
290
294
}
291
295
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 ;
297
300
298
- if ( typeof timeout === 'number' ) server . setTimeout ( timeout ) ;
301
+ if ( typeof timeout === 'number' ) server . setTimeout ( timeout ) ;
299
302
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 ) ;
304
309
305
- log ( 'http | try listen ' + port ) ;
310
+ return new Promise ( ( resolve , reject ) => {
306
311
args . push ( function listener ( err ) {
307
- resolve ( [ err , server ] ) ;
312
+ err ? reject ( err ) : resolve ( server ) ;
308
313
} ) ;
309
314
connected . apply ( null , args ) ;
310
315
} ) ;
@@ -317,73 +322,76 @@ async function createHttp(httpConfig, log) {
317
322
async function createHttps ( ssl , log , h2 ) {
318
323
if ( typeof ssl === 'undefined' ) {
319
324
log ( 'https | no options.https; no server' ) ;
320
- return [ null , null ] ;
325
+ return null ;
321
326
}
322
327
323
328
if ( Array . isArray ( ssl ) ) {
324
329
return await createMultiple ( createHttps , ssl , log , h2 ) ;
325
330
}
326
331
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
+ ] ) ;
353
337
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
+ } ) ;
357
355
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
+ }
364
359
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
+ }
370
372
373
+ return new Promise ( ( resolve , reject ) => {
371
374
args . push ( function listener ( err ) {
372
- resolve ( [ err , server ] ) ;
375
+ err ? reject ( err ) : resolve ( server ) ;
373
376
} ) ;
374
377
connected . apply ( null , args ) ;
375
378
} ) ;
376
379
}
377
380
378
381
async function createMultiple ( createFn , configArray , log ) {
379
- const errorsOrServers = await Promise . all (
382
+ const errorsOrServers = await Promise . allSettled (
380
383
configArray . map ( cfg => createFn ( cfg , log ) )
381
384
) ;
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 ;
387
396
}
388
- return [ errors . length ? errors : null , servers ] ;
389
397
}
0 commit comments