@@ -45,6 +45,7 @@ function Connection(socket, parentOrUrl, callback) {
4545 this . frameBuffer = null // string for text frames and InStream for binary frames
4646 this . outStream = null // current allocated OutStream object for sending binary frames
4747 this . key = null // the Sec-WebSocket-Key header
48+ this . headers = { } // read only map of header names and values. Header names are lower-cased
4849
4950 // Set listeners
5051 socket . on ( 'readable' , function ( ) {
@@ -244,14 +245,31 @@ Connection.prototype.startHandshake = function () {
244245 this . socket . write ( str )
245246}
246247
248+ /**
249+ * Read headers from HTTP protocol
250+ * Update the Connection#headers property
251+ * @param {string[] } lines one for each '\r\n'-separated HTTP request line
252+ */
253+ Connection . prototype . readHeaders = function ( lines ) {
254+ var i , match
255+
256+ // Extract all headers
257+ // Ignore bad-formed lines and ignore the first line (HTTP header)
258+ for ( i = 1 ; i < lines . length ; i ++ ) {
259+ if ( ( match = lines [ i ] . match ( / ^ ( [ a - z - ] + ) : ( .+ ) $ / i) ) ) {
260+ this . headers [ match [ 1 ] . toLowerCase ( ) ] = match [ 2 ]
261+ }
262+ }
263+ }
264+
247265/**
248266 * Process and check a handshake answered by a server
249267 * @param {string[] } lines one for each '\r\n'-separated HTTP request line
250268 * @returns {boolean } if the handshake was sucessful. If not, the connection must be closed
251269 * @private
252270 */
253271Connection . prototype . checkHandshake = function ( lines ) {
254- var headers , i , temp , key , sha1
272+ var key , sha1
255273
256274 // First line
257275 if ( lines . length < 4 ) {
@@ -262,30 +280,20 @@ Connection.prototype.checkHandshake = function (lines) {
262280 }
263281
264282 // Extract all headers
265- headers = { }
266- for ( i = 1 ; i < lines . length ; i ++ ) {
267- if ( ! lines [ i ] . trim ( ) ) {
268- continue
269- }
270- temp = lines [ i ] . match ( / ^ ( [ a - z - ] + ) : ( .+ ) $ / i)
271- if ( ! temp ) {
272- return false
273- }
274- headers [ temp [ 1 ] . toLowerCase ( ) ] = temp [ 2 ]
275- }
283+ this . readHeaders ( lines )
276284
277285 // Validate necessary headers
278- if ( ! ( 'upgrade' in headers ) ||
279- ! ( 'sec-websocket-accept' in headers ) ||
280- ! ( 'connection' in headers ) ) {
286+ if ( ! ( 'upgrade' in this . headers ) ||
287+ ! ( 'sec-websocket-accept' in this . headers ) ||
288+ ! ( 'connection' in this . headers ) ) {
281289 return false
282290 }
283- if ( headers . upgrade . toLowerCase ( ) !== 'websocket' ||
284- headers . connection . toLowerCase ( ) . split ( ', ' ) . indexOf ( 'upgrade' ) === - 1 ) {
291+ if ( this . headers . upgrade . toLowerCase ( ) !== 'websocket' ||
292+ this . headers . connection . toLowerCase ( ) . split ( ', ' ) . indexOf ( 'upgrade' ) === - 1 ) {
285293 return false
286294 }
287- key = headers [ 'sec-websocket-accept' ]
288- this . headers = headers
295+ key = this . headers [ 'sec-websocket-accept' ]
296+
289297 // Check the key
290298 sha1 = crypto . createHash ( 'sha1' )
291299 sha1 . end ( this . key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' )
@@ -302,7 +310,7 @@ Connection.prototype.checkHandshake = function (lines) {
302310 * @private
303311 */
304312Connection . prototype . answerHandshake = function ( lines ) {
305- var path , headers , i , temp , key , sha1
313+ var path , key , sha1
306314
307315 // First line
308316 if ( lines . length < 6 ) {
@@ -315,32 +323,22 @@ Connection.prototype.answerHandshake = function (lines) {
315323 this . path = path [ 1 ]
316324
317325 // Extract all headers
318- headers = { }
319- for ( i = 1 ; i < lines . length ; i ++ ) {
320- if ( ! lines [ i ] . trim ( ) ) {
321- continue
322- }
323- temp = lines [ i ] . match ( / ^ ( [ a - z - ] + ) : ( .+ ) $ / i)
324- if ( ! temp ) {
325- return false
326- }
327- headers [ temp [ 1 ] . toLowerCase ( ) ] = temp [ 2 ]
328- }
326+ this . readHeaders ( lines )
329327
330328 // Validate necessary headers
331- if ( ! ( 'host' in headers ) || ! ( 'sec-websocket-key' in headers ) ) {
329+ if ( ! ( 'host' in this . headers ) || ! ( 'sec-websocket-key' in this . headers ) ) {
332330 return false
333331 }
334- if ( headers . upgrade . toLowerCase ( ) !== 'websocket' ||
335- headers . connection . toLowerCase ( ) . split ( ', ' ) . indexOf ( 'upgrade' ) === - 1 ) {
332+ if ( this . headers . upgrade . toLowerCase ( ) !== 'websocket' ||
333+ this . headers . connection . toLowerCase ( ) . split ( ', ' ) . indexOf ( 'upgrade' ) === - 1 ) {
336334 return false
337335 }
338- if ( headers [ 'sec-websocket-version' ] !== '13' ) {
336+ if ( this . headers [ 'sec-websocket-version' ] !== '13' ) {
339337 return false
340338 }
341339
342- this . key = headers [ 'sec-websocket-key' ]
343- this . headers = headers
340+ this . key = this . headers [ 'sec-websocket-key' ]
341+
344342 // Build and send the response
345343 sha1 = crypto . createHash ( 'sha1' )
346344 sha1 . end ( this . key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' )
@@ -521,4 +519,4 @@ Connection.prototype.processCloseFrame = function (payload) {
521519 this . socket . write ( frame . createCloseFrame ( code , reason , ! this . server ) )
522520 this . readyState = this . CLOSED
523521 this . emit ( 'close' , code , reason )
524- }
522+ }
0 commit comments