@@ -369,8 +369,42 @@ function handleHixieUpgrade(req, socket, upgradeHead, cb) {
369
369
var location = ( ( req . headers [ 'x-forwarded-proto' ] === 'https' || socket . encrypted ) ? 'wss' : 'ws' ) + '://' + wshost + req . url
370
370
, protocol = req . headers [ 'sec-websocket-protocol' ] ;
371
371
372
+ // build the response header and return a Buffer
373
+ var buildResponseHeader = function ( ) {
374
+ var headers = [
375
+ 'HTTP/1.1 101 Switching Protocols'
376
+ , 'Upgrade: WebSocket'
377
+ , 'Connection: Upgrade'
378
+ , 'Sec-WebSocket-Location: ' + location
379
+ ] ;
380
+ if ( typeof protocol != 'undefined' ) headers . push ( 'Sec-WebSocket-Protocol: ' + protocol ) ;
381
+ if ( typeof origin != 'undefined' ) headers . push ( 'Sec-WebSocket-Origin: ' + origin ) ;
382
+
383
+ return new Buffer ( headers . concat ( '' , '' ) . join ( '\r\n' ) ) ;
384
+ } ;
385
+
386
+ // send handshake response before receiving the nonce
387
+ var handshakeResponse = function ( ) {
388
+
389
+ socket . setTimeout ( 0 ) ;
390
+ socket . setNoDelay ( true ) ;
391
+
392
+ var headerBuffer = buildResponseHeader ( ) ;
393
+
394
+ try {
395
+ socket . write ( headerBuffer , 'binary' , function ( err ) {
396
+ // remove listener if there was an error
397
+ if ( err ) socket . removeListener ( 'data' , handler ) ;
398
+ return ;
399
+ } ) ;
400
+ } catch ( e ) {
401
+ try { socket . destroy ( ) ; } catch ( e ) { }
402
+ return ;
403
+ } ;
404
+ } ;
405
+
372
406
// handshake completion code to run once nonce has been successfully retrieved
373
- var completeHandshake = function ( nonce , rest ) {
407
+ var completeHandshake = function ( nonce , rest , headerBuffer ) {
374
408
// calculate key
375
409
var k1 = req . headers [ 'sec-websocket-key1' ]
376
410
, k2 = req . headers [ 'sec-websocket-key2' ]
@@ -392,20 +426,10 @@ function handleHixieUpgrade(req, socket, upgradeHead, cb) {
392
426
} ) ;
393
427
md5 . update ( nonce . toString ( 'binary' ) ) ;
394
428
395
- var headers = [
396
- 'HTTP/1.1 101 Switching Protocols'
397
- , 'Upgrade: WebSocket'
398
- , 'Connection: Upgrade'
399
- , 'Sec-WebSocket-Location: ' + location
400
- ] ;
401
- if ( typeof protocol != 'undefined' ) headers . push ( 'Sec-WebSocket-Protocol: ' + protocol ) ;
402
- if ( typeof origin != 'undefined' ) headers . push ( 'Sec-WebSocket-Origin: ' + origin ) ;
403
-
404
429
socket . setTimeout ( 0 ) ;
405
430
socket . setNoDelay ( true ) ;
431
+
406
432
try {
407
- // merge header and hash buffer
408
- var headerBuffer = new Buffer ( headers . concat ( '' , '' ) . join ( '\r\n' ) ) ;
409
433
var hashBuffer = new Buffer ( md5 . digest ( 'binary' ) , 'binary' ) ;
410
434
var handshakeBuffer = new Buffer ( headerBuffer . length + hashBuffer . length ) ;
411
435
headerBuffer . copy ( handshakeBuffer , 0 ) ;
@@ -444,11 +468,10 @@ function handleHixieUpgrade(req, socket, upgradeHead, cb) {
444
468
if ( upgradeHead && upgradeHead . length >= nonceLength ) {
445
469
var nonce = upgradeHead . slice ( 0 , nonceLength ) ;
446
470
var rest = upgradeHead . length > nonceLength ? upgradeHead . slice ( nonceLength ) : null ;
447
- completeHandshake . call ( self , nonce , rest ) ;
471
+ completeHandshake . call ( self , nonce , rest , buildResponseHeader ( ) ) ;
448
472
}
449
473
else {
450
- // nonce not present in upgradeHead, so we must wait for enough data
451
- // data to arrive before continuing
474
+ // nonce not present in upgradeHead
452
475
var nonce = new Buffer ( nonceLength ) ;
453
476
upgradeHead . copy ( nonce , 0 ) ;
454
477
var received = upgradeHead . length ;
@@ -461,10 +484,17 @@ function handleHixieUpgrade(req, socket, upgradeHead, cb) {
461
484
if ( received == nonceLength ) {
462
485
socket . removeListener ( 'data' , handler ) ;
463
486
if ( toRead < data . length ) rest = data . slice ( toRead ) ;
464
- completeHandshake . call ( self , nonce , rest ) ;
487
+
488
+ // complete the handshake but send empty buffer for headers since they have already been sent
489
+ completeHandshake . call ( self , nonce , rest , new Buffer ( 0 ) ) ;
465
490
}
466
491
}
492
+
493
+ // handle additional data as we receive it
467
494
socket . on ( 'data' , handler ) ;
495
+
496
+ // send header response before we have the nonce to fix haproxy buffering
497
+ handshakeResponse ( ) ;
468
498
}
469
499
}
470
500
0 commit comments