@@ -10,7 +10,7 @@ module.exports = async function proxy (ctx, client) {
1010 client . dispatch ( {
1111 method : req . method ,
1212 path : req . url ,
13- headers : getRequestHeaders ( ctx ) ,
13+ headers : getHeaders ( ctx ) ,
1414 upgrade : 'Websocket'
1515 } , handler )
1616 return handler . promise
@@ -19,7 +19,7 @@ module.exports = async function proxy (ctx, client) {
1919 client . dispatch ( {
2020 method : req . method ,
2121 path : req . url ,
22- headers : getRequestHeaders ( ctx ) ,
22+ headers : getHeaders ( ctx ) ,
2323 body : req
2424 } , handler )
2525 return handler . promise
@@ -55,7 +55,7 @@ class HTTPHandler {
5555
5656 this . resume = resume
5757 this . res . on ( 'drain' , resume )
58- writeHead ( this . res , statusCode , copyHeaders ( headers , null ) )
58+ writeHead ( this . res , statusCode , getHeaders ( { headers } ) )
5959 }
6060
6161 onData ( chunk ) {
@@ -106,7 +106,7 @@ class WSHandler {
106106
107107 let head = 'HTTP/1.1 101 Switching Protocols\r\nconnection: upgrade\r\nupgrade: websocket'
108108
109- headers = copyHeaders ( headers , null )
109+ headers = getHeaders ( { headers } )
110110 for ( let n = 0 ; n < headers . length ; n += 2 ) {
111111 const key = headers [ n + 0 ]
112112 const val = headers [ n + 1 ]
@@ -132,10 +132,16 @@ class WSHandler {
132132 }
133133}
134134
135- // Update or set forwarded and via headers.
136- function getRequestHeaders ( ctx ) {
137- const { req, proxyName } = ctx
138- const { rawHeaders : headers , socket } = req
135+ // This expression matches hop-by-hop headers.
136+ // These headers are meaningful only for a single transport-level connection,
137+ // and must not be retransmitted by proxies or cached.
138+ const HOP_EXPR = / ^ ( t e | h o s t | u p g r a d e | t r a i l e r s | c o n n e c t i o n | k e e p - a l i v e | h t t p 2 - s e t t i n g s | t r a n s f e r - e n c o d i n g | p r o x y - c o n n e c t i o n | p r o x y - a u t h e n t i c a t e | p r o x y - a u t h o r i z a t i o n ) $ / i
139+
140+ // Removes hop-by-hop and pseudo headers.
141+ // Updates via and forwarded headers.
142+ // Only hop-by-hop headers may be set using the Connection general header.
143+ function getHeaders ( ctx ) {
144+ const { req, proxyName, headers = req && req . rawHeaders } = ctx
139145
140146 let via = ''
141147 let forwarded = ''
@@ -160,52 +166,6 @@ function getRequestHeaders (ctx) {
160166 }
161167 }
162168
163- const result = copyHeaders ( headers , connection )
164-
165- // TODO(fix): <host> [ ":" <port> ] vs <pseudonym>
166- // See, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Via.
167- if ( proxyName ) {
168- if ( via ) {
169- if ( via . split ( ',' ) . some ( name => name . endsWith ( proxyName ) ) ) {
170- throw new createError . LoopDetected ( )
171- }
172- via += ', '
173- }
174- via += `${ req . httpVersion } ${ proxyName } `
175- }
176-
177- if ( via ) {
178- result . push ( 'via' , via )
179- }
180-
181- result . push ( 'forwarded' , ( forwarded ? forwarded + ', ' : '' ) + [
182- `by=${ printIp ( socket . localAddress , socket . localPort ) } ` ,
183- `for=${ printIp ( socket . remoteAddress , socket . remotePort ) } ` ,
184- `proto=${ socket . encrypted ? 'https' : 'http' } ` ,
185- `host=${ printIp ( authority || host || '' ) } `
186- ] . join ( ';' ) )
187-
188- return result
189- }
190-
191- // This expression matches hop-by-hop headers.
192- // These headers are meaningful only for a single transport-level connection,
193- // and must not be retransmitted by proxies or cached.
194- const HOP_EXPR = / ^ ( t e | h o s t | u p g r a d e | t r a i l e r s | c o n n e c t i o n | k e e p - a l i v e | h t t p 2 - s e t t i n g s | t r a n s f e r - e n c o d i n g | p r o x y - c o n n e c t i o n | p r o x y - a u t h e n t i c a t e | p r o x y - a u t h o r i z a t i o n ) $ / i
195-
196- // Removes hop-by-hop and pseudo headers.
197- // Only hop-by-hop headers may be set using the Connection general header.
198- function copyHeaders ( headers , connection ) {
199- if ( ! connection ) {
200- for ( let n = 0 ; n < headers . length ; n += 2 ) {
201- const key = headers [ n + 0 ]
202- if ( key . length === 10 && key . toLowerCase ( ) === 'connection' ) {
203- connection = headers [ n + 1 ]
204- break
205- }
206- }
207- }
208-
209169 let remove
210170 if ( connection && ! HOP_EXPR . test ( connection ) ) {
211171 remove = connection . split ( / , \s * / )
@@ -225,6 +185,33 @@ function copyHeaders (headers, connection) {
225185 }
226186 }
227187
188+ if ( req ) {
189+ const { socket, httpVersion } = req
190+
191+ result . push ( 'forwarded' , ( forwarded ? forwarded + ', ' : '' ) + [
192+ `by=${ printIp ( socket . localAddress , socket . localPort ) } ` ,
193+ `for=${ printIp ( socket . remoteAddress , socket . remotePort ) } ` ,
194+ `proto=${ socket . encrypted ? 'https' : 'http' } ` ,
195+ `host=${ printIp ( authority || host || '' ) } `
196+ ] . join ( ';' ) )
197+
198+ // TODO(fix): <host> [ ":" <port> ] vs <pseudonym>
199+ // See, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Via.
200+ if ( proxyName ) {
201+ if ( via ) {
202+ if ( via . split ( ',' ) . some ( name => name . endsWith ( proxyName ) ) ) {
203+ throw new createError . LoopDetected ( )
204+ }
205+ via += ', '
206+ }
207+ via += `${ httpVersion } ${ proxyName } `
208+ }
209+ }
210+
211+ if ( via ) {
212+ result . push ( 'via' , via )
213+ }
214+
228215 return result
229216}
230217
0 commit comments