@@ -553,17 +553,29 @@ HttpProxy.prototype._forwardRequest = function (req) {
553
553
} ;
554
554
555
555
HttpProxy . prototype . proxyWebSocketRequest = function ( req , socket , head , options ) {
556
- var self = this , outgoing , errState = false , CRLF = '\r\n' ;
556
+ var self = this ,
557
+ listeners = { } ,
558
+ errState = false ,
559
+ CRLF = '\r\n' ,
560
+ outgoing ;
557
561
558
- // WebSocket requests has method = GET
562
+ //
563
+ // WebSocket requests must have the `GET` method and
564
+ // the `upgrade:websocket` header
565
+ //
559
566
if ( req . method !== 'GET' || req . headers . upgrade . toLowerCase ( ) !== 'websocket' ) {
567
+ //
560
568
// This request is not WebSocket request
569
+ //
561
570
return ;
562
571
}
563
572
564
- // Turn of all bufferings
565
- // For server set KeepAlive
566
- // For client set encoding
573
+ //
574
+ // Helper function for setting appropriate socket values:
575
+ // 1. Turn of all bufferings
576
+ // 2. For server set KeepAlive
577
+ // 3. For client set encoding
578
+ //
567
579
function _socket ( socket , keepAlive ) {
568
580
socket . setTimeout ( 0 ) ;
569
581
socket . setNoDelay ( true ) ;
@@ -580,20 +592,25 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
580
592
}
581
593
}
582
594
583
- function onUpgrade ( reverseProxy , proxySocket ) {
595
+ //
596
+ // On `upgrade` from the Agent socket, listen to
597
+ // the appropriate events.
598
+ //
599
+ function onUpgrade ( reverseProxy , proxySocket ) {
584
600
if ( ! reverseProxy ) {
585
601
proxySocket . end ( ) ;
586
602
socket . end ( ) ;
587
603
return ;
588
604
}
589
605
590
- var listeners = { } ;
591
-
592
- // We're now connected to the server, so lets change server socket
593
- proxySocket . on ( 'data' , listeners . _r_data = function ( data ) {
594
- // Pass data to client
606
+ //
607
+ // Any incoming data on this WebSocket to the proxy target
608
+ // will be written to the `reverseProxy` socket.
609
+ //
610
+ proxySocket . on ( 'data' , listeners . onIncoming = function ( data ) {
595
611
if ( reverseProxy . incoming . socket . writable ) {
596
612
try {
613
+ self . emit ( 'websocket:outgoing' , req , socket , head , data ) ;
597
614
reverseProxy . incoming . socket . write ( data ) ;
598
615
}
599
616
catch ( e ) {
@@ -603,62 +620,88 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
603
620
}
604
621
} ) ;
605
622
606
- reverseProxy . incoming . socket . on ( 'data' , listeners . _data = function ( data ) {
607
- // Pass data from client to server
623
+ //
624
+ // Any outgoing data on this Websocket from the proxy target
625
+ // will be written to the `proxySocket` socket.
626
+ //
627
+ reverseProxy . incoming . socket . on ( 'data' , listeners . onOutgoing = function ( data ) {
608
628
try {
629
+ self . emit ( 'websocket:incoming' , reverseProxy , reverseProxy . incoming , head , data ) ;
609
630
proxySocket . write ( data ) ;
610
631
}
611
632
catch ( e ) {
612
633
proxySocket . end ( ) ;
613
634
socket . end ( ) ;
614
635
}
615
636
} ) ;
616
-
617
- // Detach event listeners from reverseProxy
637
+
638
+ //
639
+ // Helper function to detach all event listeners
640
+ // from `reverseProxy` and `proxySocket`.
641
+ //
618
642
function detach ( ) {
619
- proxySocket . removeListener ( 'end' , listeners . _r_close ) ;
620
- proxySocket . removeListener ( 'data' , listeners . _r_data ) ;
621
- reverseProxy . incoming . socket . removeListener ( 'data ' , listeners . _data ) ;
622
- reverseProxy . incoming . socket . removeListener ( 'end ' , listeners . _close ) ;
643
+ proxySocket . removeListener ( 'end' , listeners . onIncomingClose ) ;
644
+ proxySocket . removeListener ( 'data' , listeners . onIncoming ) ;
645
+ reverseProxy . incoming . socket . removeListener ( 'end ' , listeners . onOutgoingClose ) ;
646
+ reverseProxy . incoming . socket . removeListener ( 'data ' , listeners . onOutgoing ) ;
623
647
}
624
648
625
- // Hook disconnections
626
- proxySocket . on ( 'end' , listeners . _r_close = function ( ) {
649
+ //
650
+ // If the incoming `proxySocket` socket closes, then
651
+ // detach all event listeners.
652
+ //
653
+ proxySocket . on ( 'end' , listeners . onIncomingClose = function ( ) {
627
654
reverseProxy . incoming . socket . end ( ) ;
628
655
detach ( ) ;
656
+
657
+ // Emit the `end` event now that we have completed proxying
658
+ self . emit ( 'websocket:end' , req , socket , head ) ;
629
659
} ) ;
630
660
631
- reverseProxy . incoming . socket . on ( 'end' , listeners . _close = function ( ) {
661
+ //
662
+ // If the `reverseProxy` socket closes, then detach all
663
+ // event listeners.
664
+ //
665
+ reverseProxy . incoming . socket . on ( 'end' , listeners . onOutgoingClose = function ( ) {
632
666
proxySocket . end ( ) ;
633
667
detach ( ) ;
634
668
} ) ;
635
669
} ;
636
670
637
- // Client socket
671
+ // Setup the incoming client socket.
638
672
_socket ( socket ) ;
639
673
640
- // Remote host address
674
+ //
675
+ // Get the protocol, and host for this request and create an instance
676
+ // of `http.Agent` or `https.Agent` from the pool managed by `node-http-proxy`.
677
+ //
641
678
var protocolName = options . https || this . target . https ? 'https' : 'http' ,
642
- agent = _getAgent ( options . host , options . port , options . https || this . target . https ) ,
643
- remoteHost = options . host + ( options . port - 80 === 0 ? '' : ':' + options . port ) ;
679
+ remoteHost = options . host + ( options . port - 80 === 0 ? '' : ':' + options . port ) ,
680
+ agent = _getAgent ( options . host , options . port , options . https || this . target . https ) ;
644
681
645
- // Change headers
682
+ // Change headers (if requested).
646
683
if ( this . changeOrigin ) {
647
684
req . headers . host = remoteHost ;
648
685
req . headers . origin = protocolName + '://' + remoteHost ;
649
686
}
650
687
688
+ //
689
+ // Make the outgoing WebSocket request
690
+ //
651
691
outgoing = {
652
692
host : options . host ,
653
693
port : options . port ,
654
694
method : 'GET' ,
655
695
path : req . url ,
656
696
headers : req . headers ,
657
697
} ;
658
-
659
- // Make the outgoing WebSocket request
660
698
var reverseProxy = agent . appendMessage ( outgoing ) ;
661
699
700
+ //
701
+ // On any errors from the `reverseProxy` emit the
702
+ // `webSocketProxyError` and close the appropriate
703
+ // connections.
704
+ //
662
705
function proxyError ( err ) {
663
706
reverseProxy . end ( ) ;
664
707
if ( self . emit ( 'webSocketProxyError' , req , socket , head ) ) {
@@ -703,7 +746,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
703
746
704
747
//
705
748
// If the reverseProxy connection has an underlying socket,
706
- // then behing the handshake.
749
+ // then execute the WebSocket handshake.
707
750
//
708
751
if ( typeof reverseProxy . socket !== 'undefined' ) {
709
752
reverseProxy . socket . on ( 'data' , function handshake ( data ) {
@@ -741,6 +784,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
741
784
// Write the printable and non-printable data to the socket
742
785
// from the original incoming request.
743
786
//
787
+ self . emit ( 'websocket:handshake' , req , socket , head , sdata , data ) ;
744
788
socket . write ( sdata ) ;
745
789
socket . write ( data ) ;
746
790
}
0 commit comments