bare-http1 3.4.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,12 +20,18 @@ module.exports = class HTTPClientConnection {
20
20
  this._read = 0
21
21
  this._buffer = null
22
22
 
23
+ this._onerror = this._onerror.bind(this)
24
+ this._onclose = this._onclose.bind(this)
25
+ this._onend = this._onend.bind(this)
26
+ this._ondata = this._ondata.bind(this)
27
+ this._ondrain = this._ondrain.bind(this)
28
+
23
29
  socket
24
- .on('error', this._onerror.bind(this))
25
- .on('close', this._onclose.bind(this))
26
- .on('end', this._onend.bind(this))
27
- .on('data', this._ondata.bind(this))
28
- .on('drain', this._ondrain.bind(this))
30
+ .on('error', this._onerror)
31
+ .on('close', this._onclose)
32
+ .on('end', this._onend)
33
+ .on('data', this._ondata)
34
+ .on('drain', this._ondrain)
29
35
  }
30
36
 
31
37
  _onerror (err) {
@@ -106,7 +112,7 @@ module.exports = class HTTPClientConnection {
106
112
  const r = data.toString().split('\r\n')
107
113
  if (r.length === 0) return this.socket.destroy()
108
114
 
109
- const [, statusCode, statusMessage] = r[0].split(' ')
115
+ const [, statusCode, ...statusMessage] = r[0].split(' ')
110
116
  if (!statusCode || !statusMessage) return this.socket.destroy()
111
117
 
112
118
  const headers = {}
@@ -116,11 +122,18 @@ module.exports = class HTTPClientConnection {
116
122
  headers[name.toLowerCase()] = value
117
123
  }
118
124
 
119
- this.res = new this._IncomingMessage(this.socket, headers, { statusCode: parseInt(statusCode, 10), statusMessage })
120
-
121
125
  this.req.on('close', () => { this.req = null })
126
+
127
+ this.res = new this._IncomingMessage(this.socket, headers, { statusCode: parseInt(statusCode, 10), statusMessage: statusMessage.join(' ') })
128
+
122
129
  this.res.on('close', () => { this.res = null; this._onreset() })
123
130
 
131
+ if (headers.connection && headers.connection.toLowerCase() === 'upgrade') {
132
+ const head = this._buffer
133
+ this._buffer = null
134
+ return this._onupgrade(head)
135
+ }
136
+
124
137
  this.req.emit('response', this.res)
125
138
 
126
139
  if (headers['transfer-encoding'] === 'chunked') {
@@ -163,6 +176,24 @@ module.exports = class HTTPClientConnection {
163
176
  if (this._read === this._length) this._onfinished()
164
177
  }
165
178
 
179
+ _onupgrade (head) {
180
+ this.socket
181
+ .off('error', this._onerror)
182
+ .off('close', this._onclose)
183
+ .off('end', this._onend)
184
+ .off('data', this._ondata)
185
+ .off('drain', this._ondrain)
186
+
187
+ const req = this.req
188
+
189
+ req.upgrade = true
190
+ req.destroy()
191
+
192
+ if (req.emit('upgrade', this.res, this.socket, head)) return
193
+
194
+ this.socket.destroy()
195
+ }
196
+
166
197
  _onfinished () {
167
198
  if (this.res) this.res.push(null)
168
199
  if (this.req) this.req._continueFinal()
@@ -35,15 +35,20 @@ module.exports = class HTTPClientRequest extends HTTPOutgoingMessage {
35
35
  _header () {
36
36
  let h = `${this.method} ${this.path} HTTP/1.1\r\n`
37
37
 
38
+ let upgrade = false
39
+
38
40
  for (const name of Object.keys(this.headers)) {
39
41
  const n = name.toLowerCase()
40
42
  const v = this.headers[name]
41
43
 
42
44
  if (n === 'content-length') this._chunked = false
45
+ if (n === 'connection' && v && v.toLowerCase() === 'upgrade') upgrade = true
43
46
 
44
47
  h += `${httpCase(n)}: ${v}\r\n`
45
48
  }
46
49
 
50
+ if (upgrade) this._chunked = false
51
+
47
52
  if (this._chunked) h += 'Transfer-Encoding: chunked\r\n'
48
53
 
49
54
  h += '\r\n'
@@ -74,6 +79,12 @@ module.exports = class HTTPClientRequest extends HTTPOutgoingMessage {
74
79
  this._pendingFinal = cb
75
80
  }
76
81
 
82
+ _predestroy () {
83
+ if (this.upgrade) return this._continueFinal()
84
+
85
+ this.socket.destroy()
86
+ }
87
+
77
88
  _continueWrite () {
78
89
  if (this._pendingWrite === null) return
79
90
  const cb = this._pendingWrite
@@ -6,6 +6,7 @@ module.exports = class HTTPIncomingMessage extends Readable {
6
6
 
7
7
  this.socket = socket
8
8
  this.headers = headers
9
+ this.upgrade = false
9
10
 
10
11
  // Server arguments
11
12
  this.method = args.method || ''
@@ -33,6 +34,6 @@ module.exports = class HTTPIncomingMessage extends Readable {
33
34
  }
34
35
 
35
36
  _predestroy () {
36
- this.socket.destroy()
37
+ if (this.upgrade === false) this.socket.destroy()
37
38
  }
38
39
  }
@@ -8,6 +8,7 @@ module.exports = class HTTPOutgoingMessage extends Writable {
8
8
  this.socket = socket
9
9
  this.headers = {}
10
10
  this.headersSent = false
11
+ this.upgrade = false
11
12
  }
12
13
 
13
14
  getHeader (name) {
@@ -38,7 +39,7 @@ module.exports = class HTTPOutgoingMessage extends Writable {
38
39
  }
39
40
 
40
41
  _predestroy () {
41
- this.socket.destroy()
42
+ if (this.upgrade === false) this.socket.destroy()
42
43
  }
43
44
  }
44
45
 
@@ -23,10 +23,14 @@ module.exports = class HTTPServerConnection {
23
23
  this._read = 0
24
24
  this._buffer = null
25
25
 
26
+ this._onerror = this._onerror.bind(this)
27
+ this._ondata = this._ondata.bind(this)
28
+ this._ondrain = this._ondrain.bind(this)
29
+
26
30
  socket
27
- .on('error', this._onerror.bind(this))
28
- .on('data', this._ondata.bind(this))
29
- .on('drain', this._ondrain.bind(this))
31
+ .on('error', this._onerror)
32
+ .on('data', this._ondata)
33
+ .on('drain', this._ondrain)
30
34
  }
31
35
 
32
36
  _onerror (err) {
@@ -110,10 +114,18 @@ module.exports = class HTTPServerConnection {
110
114
  }
111
115
 
112
116
  this.req = new this._IncomingMessage(this.socket, headers, { method, url })
117
+
118
+ this.req.on('close', () => { this.req = null; this._onreset() })
119
+
120
+ if (headers.connection && headers.connection.toLowerCase() === 'upgrade') {
121
+ const head = this._buffer
122
+ this._buffer = null
123
+ return this._onupgrade(head)
124
+ }
125
+
113
126
  this.res = new this._ServerResponse(this.socket, this.req, headers.connection === 'close')
114
127
 
115
128
  this.res.on('close', () => { this.res = null })
116
- this.req.on('close', () => { this.req = null; this._onreset() })
117
129
 
118
130
  this.server.emit('request', this.req, this.res)
119
131
 
@@ -157,6 +169,20 @@ module.exports = class HTTPServerConnection {
157
169
  if (this._read === this._length) this._onfinished()
158
170
  }
159
171
 
172
+ _onupgrade (head) {
173
+ this.socket
174
+ .off('error', this._onerror)
175
+ .off('data', this._ondata)
176
+ .off('drain', this._ondrain)
177
+
178
+ const req = this.req
179
+
180
+ req.upgrade = true
181
+ req.destroy()
182
+
183
+ this.server.emit('upgrade', req, this.socket, head)
184
+ }
185
+
160
186
  _onfinished () {
161
187
  if (this.req) this.req.push(null)
162
188
  }
@@ -42,7 +42,7 @@ module.exports = class HTTPServerResponse extends HTTPOutgoingMessage {
42
42
  const v = this.headers[name]
43
43
 
44
44
  if (n === 'content-length') this._chunked = false
45
- if (n === 'connection' && v === 'close') this._close = true
45
+ if (n === 'connection' && v && v.toLowerCase() === 'close') this._close = true
46
46
 
47
47
  h += httpCase(n) + ': ' + v + '\r\n'
48
48
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-http1",
3
- "version": "3.4.0",
3
+ "version": "3.5.0",
4
4
  "description": "Native HTTP/1 library for JavaScript",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -31,9 +31,6 @@
31
31
  },
32
32
  "devDependencies": {
33
33
  "brittle": "^3.3.0",
34
- "mime-types": "^2.1.35",
35
- "pump": "^3.0.0",
36
- "range-parser": "^1.2.1",
37
34
  "standard": "^17.0.0"
38
35
  }
39
36
  }