@@ -90,6 +90,7 @@ const kMaybeDestroy = Symbol('maybe-destroy');
90
90
const kLocalSettings = Symbol ( 'local-settings' ) ;
91
91
const kOptions = Symbol ( 'options' ) ;
92
92
const kOwner = Symbol ( 'owner' ) ;
93
+ const kOrigin = Symbol ( 'origin' ) ;
93
94
const kProceed = Symbol ( 'proceed' ) ;
94
95
const kProtocol = Symbol ( 'protocol' ) ;
95
96
const kProxySocket = Symbol ( 'proxy-socket' ) ;
@@ -152,6 +153,7 @@ const {
152
153
HTTP_STATUS_NO_CONTENT ,
153
154
HTTP_STATUS_NOT_MODIFIED ,
154
155
HTTP_STATUS_SWITCHING_PROTOCOLS ,
156
+ HTTP_STATUS_MISDIRECTED_REQUEST ,
155
157
156
158
STREAM_OPTION_EMPTY_PAYLOAD ,
157
159
STREAM_OPTION_GET_TRAILERS
@@ -242,6 +244,11 @@ function onSessionHeaders(handle, id, cat, flags, headers) {
242
244
} else {
243
245
event = endOfStream ? 'trailers' : 'headers' ;
244
246
}
247
+ const session = stream . session ;
248
+ if ( status === HTTP_STATUS_MISDIRECTED_REQUEST ) {
249
+ const originSet = session [ kState ] . originSet = initOriginSet ( session ) ;
250
+ originSet . delete ( stream [ kOrigin ] ) ;
251
+ }
245
252
debug ( `Http2Stream ${ id } [Http2Session ` +
246
253
`${ sessionName ( type ) } ]: emitting stream '${ event } ' event` ) ;
247
254
process . nextTick ( emit , stream , event , obj , flags , headers ) ;
@@ -404,6 +411,39 @@ function onAltSvc(stream, origin, alt) {
404
411
session . emit ( 'altsvc' , alt , origin , stream ) ;
405
412
}
406
413
414
+ function initOriginSet ( session ) {
415
+ let originSet = session [ kState ] . originSet ;
416
+ if ( originSet === undefined ) {
417
+ const socket = session [ kSocket ] ;
418
+ session [ kState ] . originSet = originSet = new Set ( ) ;
419
+ if ( socket . servername != null ) {
420
+ let originString = `https://${ socket . servername } ` ;
421
+ if ( socket . remotePort != null )
422
+ originString += `:${ socket . remotePort } ` ;
423
+ // We have to ensure that it is a properly serialized
424
+ // ASCII origin string. The socket.servername might not
425
+ // be properly ASCII encoded.
426
+ originSet . add ( ( new URL ( originString ) ) . origin ) ;
427
+ }
428
+ }
429
+ return originSet ;
430
+ }
431
+
432
+ function onOrigin ( origins ) {
433
+ const session = this [ kOwner ] ;
434
+ if ( session . destroyed )
435
+ return ;
436
+ debug ( `Http2Session ${ sessionName ( session [ kType ] ) } : origin received: ` +
437
+ `${ origins . join ( ', ' ) } ` ) ;
438
+ session [ kUpdateTimer ] ( ) ;
439
+ if ( ! session . encrypted || session . destroyed )
440
+ return undefined ;
441
+ const originSet = initOriginSet ( session ) ;
442
+ for ( var n = 0 ; n < origins . length ; n ++ )
443
+ originSet . add ( origins [ n ] ) ;
444
+ session . emit ( 'origin' , origins ) ;
445
+ }
446
+
407
447
// Receiving a GOAWAY frame from the connected peer is a signal that no
408
448
// new streams should be created. If the code === NGHTTP2_NO_ERROR, we
409
449
// are going to send our close, but allow existing frames to close
@@ -766,6 +806,7 @@ function setupHandle(socket, type, options) {
766
806
handle . onframeerror = onFrameError ;
767
807
handle . ongoawaydata = onGoawayData ;
768
808
handle . onaltsvc = onAltSvc ;
809
+ handle . onorigin = onOrigin ;
769
810
770
811
if ( typeof options . selectPadding === 'function' )
771
812
handle . ongetpadding = onSelectPadding ( options . selectPadding ) ;
@@ -792,6 +833,12 @@ function setupHandle(socket, type, options) {
792
833
options . settings : { } ;
793
834
794
835
this . settings ( settings ) ;
836
+
837
+ if ( type === NGHTTP2_SESSION_SERVER &&
838
+ Array . isArray ( options . origins ) ) {
839
+ this . origin ( ...options . origins ) ;
840
+ }
841
+
795
842
process . nextTick ( emit , this , 'connect' , this , socket ) ;
796
843
}
797
844
@@ -930,23 +977,7 @@ class Http2Session extends EventEmitter {
930
977
get originSet ( ) {
931
978
if ( ! this . encrypted || this . destroyed )
932
979
return undefined ;
933
-
934
- let originSet = this [ kState ] . originSet ;
935
- if ( originSet === undefined ) {
936
- const socket = this [ kSocket ] ;
937
- this [ kState ] . originSet = originSet = new Set ( ) ;
938
- if ( socket . servername != null ) {
939
- let originString = `https://${ socket . servername } ` ;
940
- if ( socket . remotePort != null )
941
- originString += `:${ socket . remotePort } ` ;
942
- // We have to ensure that it is a properly serialized
943
- // ASCII origin string. The socket.servername might not
944
- // be properly ASCII encoded.
945
- originSet . add ( ( new URL ( originString ) ) . origin ) ;
946
- }
947
- }
948
-
949
- return Array . from ( originSet ) ;
980
+ return Array . from ( initOriginSet ( this ) ) ;
950
981
}
951
982
952
983
// True if the Http2Session is still waiting for the socket to connect
@@ -1324,6 +1355,41 @@ class ServerHttp2Session extends Http2Session {
1324
1355
1325
1356
this [ kHandle ] . altsvc ( stream , origin || '' , alt ) ;
1326
1357
}
1358
+
1359
+ // Submits an origin frame to be sent.
1360
+ origin ( ...origins ) {
1361
+ if ( this . destroyed )
1362
+ throw new errors . Error ( 'ERR_HTTP2_INVALID_SESSION' ) ;
1363
+
1364
+ if ( origins . length === 0 )
1365
+ return ;
1366
+
1367
+ let arr = '' ;
1368
+ let len = 0 ;
1369
+ const count = origins . length ;
1370
+ for ( var i = 0 ; i < count ; i ++ ) {
1371
+ let origin = origins [ i ] ;
1372
+ if ( typeof origin === 'string' ) {
1373
+ origin = ( new URL ( origin ) ) . origin ;
1374
+ } else if ( origin != null && typeof origin === 'object' ) {
1375
+ origin = origin . origin ;
1376
+ }
1377
+ if ( typeof origin !== 'string' )
1378
+ throw new errors . Error ( 'ERR_INVALID_ARG_TYPE' , 'origin' , 'string' ,
1379
+ origin ) ;
1380
+ if ( origin === 'null' )
1381
+ throw new errors . Error ( 'ERR_HTTP2_INVALID_ORIGIN' ) ;
1382
+
1383
+ arr += `${ origin } \0` ;
1384
+ len += origin . length ;
1385
+ }
1386
+
1387
+ if ( len > 16382 )
1388
+ throw new errors . Error ( 'ERR_HTTP2_ORIGIN_LENGTH' ) ;
1389
+
1390
+ this [ kHandle ] . origin ( arr , count ) ;
1391
+ }
1392
+
1327
1393
}
1328
1394
1329
1395
// ClientHttp2Session instances have to wait for the socket to connect after
@@ -1394,6 +1460,8 @@ class ClientHttp2Session extends Http2Session {
1394
1460
1395
1461
const stream = new ClientHttp2Stream ( this , undefined , undefined , { } ) ;
1396
1462
stream [ kSentHeaders ] = headers ;
1463
+ stream [ kOrigin ] = `${ headers [ HTTP2_HEADER_SCHEME ] } ://` +
1464
+ `${ headers [ HTTP2_HEADER_AUTHORITY ] } ` ;
1397
1465
1398
1466
// Close the writable side of the stream if options.endStream is set.
1399
1467
if ( options . endStream )
0 commit comments