bare-http1 4.3.1 → 4.5.1

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.
package/index.d.ts CHANGED
@@ -99,6 +99,8 @@ export interface HTTPAgentOptions {
99
99
  }
100
100
 
101
101
  export interface HTTPAgent {
102
+ readonly suspended: boolean
103
+ readonly resumed: Promise<void> | null
102
104
  readonly sockets: IterableIterator<TCPSocket>
103
105
  readonly freeSockets: IterableIterator<TCPSocket>
104
106
 
@@ -112,6 +114,8 @@ export interface HTTPAgent {
112
114
 
113
115
  addRequest(req: HTTPClientRequest, opts: TCPSocketOptions & TCPSocketConnectOptions): void
114
116
 
117
+ suspend(): void
118
+ resume(): void
115
119
  destroy(): void
116
120
  }
117
121
 
package/lib/agent.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const EventEmitter = require('bare-events')
2
2
  const tcp = require('bare-tcp')
3
3
  const HTTPClientConnection = require('./client-connection')
4
+ const errors = require('./errors')
4
5
 
5
6
  class HTTPSocketSet {
6
7
  constructor() {
@@ -66,16 +67,28 @@ class HTTPAgent extends EventEmitter {
66
67
  constructor(opts = {}) {
67
68
  super()
68
69
 
69
- const { keepAlive = false, keepAliveMsecs = 1000 } = opts
70
+ const { keepAlive = false, keepAliveMsecs = 1000, defaultPort = 80 } = opts
71
+
72
+ this._suspended = false
73
+ this._resuming = null
70
74
 
71
75
  this._sockets = new HTTPSocketSet()
72
76
  this._freeSockets = new HTTPSocketSet()
73
77
 
74
78
  this._keepAlive = typeof keepAlive === 'number' ? keepAlive : keepAlive ? keepAliveMsecs : -1
79
+ this._defaultPort = defaultPort
75
80
 
76
81
  this._opts = { ...opts }
77
82
  }
78
83
 
84
+ get suspended() {
85
+ return this._suspended
86
+ }
87
+
88
+ get resumed() {
89
+ return this._resuming ? this._resuming.promise : null
90
+ }
91
+
79
92
  get sockets() {
80
93
  return this._sockets.sockets()
81
94
  }
@@ -84,7 +97,13 @@ class HTTPAgent extends EventEmitter {
84
97
  return this._freeSockets.sockets()
85
98
  }
86
99
 
100
+ get defaultPort() {
101
+ return this._defaultPort
102
+ }
103
+
87
104
  createConnection(opts) {
105
+ if (this._suspended) throw errors.AGENT_SUSPENDED()
106
+
88
107
  return tcp.createConnection(opts)
89
108
  }
90
109
 
@@ -120,10 +139,10 @@ class HTTPAgent extends EventEmitter {
120
139
 
121
140
  socket
122
141
  .on('free', onfree)
123
- .on('timeout', ontimeout)
124
142
  .on('end', onremove)
125
143
  .on('finish', onremove)
126
144
  .on('close', onremove)
145
+ .on('timeout', ontimeout)
127
146
 
128
147
  function onfree() {
129
148
  if (socket.destroyed) return
@@ -137,12 +156,6 @@ class HTTPAgent extends EventEmitter {
137
156
  agent.emit('free', socket)
138
157
  }
139
158
 
140
- function ontimeout() {
141
- socket.destroy()
142
-
143
- agent._freeSockets.delete(name, socket)
144
- }
145
-
146
159
  function onremove() {
147
160
  socket.off('free', onfree)
148
161
 
@@ -151,37 +164,57 @@ class HTTPAgent extends EventEmitter {
151
164
 
152
165
  if (agent._sockets.size === 0) HTTPAgent._agents.delete(agent)
153
166
  }
167
+
168
+ function ontimeout() {
169
+ socket.destroy()
170
+
171
+ agent._freeSockets.delete(name, socket)
172
+ }
154
173
  }
155
174
 
156
175
  if (this._sockets.size === 0) HTTPAgent._agents.add(this)
157
176
 
158
177
  this._sockets.add(name, socket)
159
178
 
160
- req.socket = socket
179
+ req._socket = socket
161
180
 
162
181
  const connection = HTTPClientConnection.from(socket, opts)
163
182
 
164
- connection.req = req
183
+ connection._req = req
184
+ }
185
+
186
+ suspend() {
187
+ if (this._suspended) return
188
+
189
+ this._resuming = Promise.withResolvers()
190
+ this._suspended = true
191
+
192
+ this.destroy()
193
+ }
194
+
195
+ resume() {
196
+ if (this._resuming === null) return
197
+
198
+ this._resuming.resolve()
199
+ this._resuming = null
200
+ this._suspended = false
165
201
  }
166
202
 
167
203
  destroy() {
168
204
  for (const socket of this._sockets.sockets()) socket.destroy()
169
205
  }
170
206
 
171
- static _global = new this({ keepAlive: 1000, timeout: 5000 })
172
207
  static _agents = new Set()
173
208
 
174
- static get global() {
175
- return this._global
176
- }
177
-
178
209
  static _onidle() {
179
210
  for (const agent of this._agents) {
180
- for (const socket of agent._sockets.sockets()) socket.destroy()
211
+ agent.destroy()
181
212
  }
182
213
  }
183
214
  }
184
215
 
216
+ HTTPAgent.global = new HTTPAgent({ keepAlive: 1000, timeout: 5000 })
217
+
185
218
  module.exports = HTTPAgent
186
219
 
187
220
  Bare.on('idle', HTTPAgent._onidle.bind(HTTPAgent))
@@ -22,10 +22,10 @@ module.exports = class HTTPClientConnection {
22
22
  constructor(socket, opts = {}) {
23
23
  const { IncomingMessage = HTTPIncomingMessage } = opts
24
24
 
25
- this.socket = socket
25
+ this._socket = socket
26
26
 
27
- this.req = null
28
- this.res = null
27
+ this._req = null
28
+ this._res = null
29
29
 
30
30
  this._IncomingMessage = IncomingMessage
31
31
 
@@ -50,20 +50,32 @@ module.exports = class HTTPClientConnection {
50
50
  HTTPClientConnection._connections.set(socket, this)
51
51
  }
52
52
 
53
+ get socket() {
54
+ return this._socket
55
+ }
56
+
57
+ get req() {
58
+ return this._req
59
+ }
60
+
61
+ get res() {
62
+ return this._res
63
+ }
64
+
53
65
  get idle() {
54
66
  return this._idle
55
67
  }
56
68
 
57
69
  _onerror(err) {
58
- if (this.req) this.req.destroy(err)
70
+ if (this._req) this._req.destroy(err)
59
71
  }
60
72
 
61
73
  _onclose() {
62
- if (this.req) this.req._continueFinal()
74
+ if (this._req) this._req.destroy()
63
75
  }
64
76
 
65
77
  _onend() {
66
- if (this.req) this.req.destroy(errors.CONNECTION_LOST())
78
+ if (this._req) this._req.destroy(errors.CONNECTION_LOST())
67
79
  }
68
80
 
69
81
  _ondata(data) {
@@ -73,68 +85,77 @@ module.exports = class HTTPClientConnection {
73
85
  for (const op of this._parser.push(data)) {
74
86
  switch (op.type) {
75
87
  case RESPONSE:
76
- this.req.on('close', () => {
77
- this.req = null
88
+ this._req.on('close', () => {
89
+ this._req = null
78
90
  })
79
91
 
80
- this.res = new this._IncomingMessage(this.socket, op.headers, {
92
+ this._res = new this._IncomingMessage(this._socket, op.headers, {
81
93
  statusCode: op.code,
82
94
  statusMessage: op.reason
83
95
  })
84
96
 
85
- this.res.on('close', () => {
86
- this.res = null
87
-
97
+ this._res.on('close', () => {
98
+ this._res = null
88
99
  this._idle = true
89
100
 
90
- this.socket.emit('free')
101
+ this._socket.emit('free')
91
102
  })
92
103
 
93
104
  if (op.headers.connection && op.headers.connection.toLowerCase() === 'upgrade') {
94
105
  return this._onupgrade(this._parser.end())
95
106
  }
96
107
 
97
- this.req.emit('response', this.res)
108
+ this._req.emit('response', this._res)
98
109
  break
99
110
 
100
111
  case DATA:
101
- this.res.push(op.data)
112
+ this._res.push(op.data)
102
113
  break
103
114
 
104
115
  case END:
105
- if (this.res) this.res.push(null)
106
- if (this.req) this.req._continueFinal()
116
+ if (this._res) {
117
+ this._res._socket = null
118
+ this._res.push(null)
119
+ }
120
+
121
+ if (this._req) {
122
+ this._req._socket = null
123
+ this._req.destroy()
124
+ }
107
125
  break
108
126
  }
109
127
  }
110
128
  } catch (err) {
111
- this.socket.destroy(err)
129
+ this._socket.destroy(err)
112
130
  }
113
131
  }
114
132
 
115
133
  _onupgrade(data) {
116
- this._ondetach()
134
+ this._detach()
117
135
 
118
- const req = this.req
136
+ const res = this._res
137
+ const req = this._req
119
138
 
120
- req.upgrade = true
121
- req.destroy()
139
+ res._upgrade = req._upgrade = true
140
+
141
+ const upgraded = req.emit('upgrade', res, this._socket, data || EMPTY)
122
142
 
123
- if (req.emit('upgrade', this.res, this.socket, data || EMPTY)) return
143
+ res.push(null)
144
+ req.destroy()
124
145
 
125
- this.socket.destroy()
146
+ if (!upgraded) this._socket.destroy()
126
147
  }
127
148
 
128
149
  _ontimeout() {
129
- if (this.req) this.req.emit('timeout')
150
+ if (this._req) this._req.emit('timeout')
130
151
  }
131
152
 
132
153
  _ondrain() {
133
- if (this.req) this.req._continueWrite()
154
+ if (this._req) this._req._continueWrite()
134
155
  }
135
156
 
136
- _ondetach() {
137
- this.socket
157
+ _detach() {
158
+ this._socket
138
159
  .off('error', this._onerror)
139
160
  .off('close', this._onclose)
140
161
  .off('end', this._onend)
@@ -142,6 +163,6 @@ module.exports = class HTTPClientConnection {
142
163
  .off('drain', this._ondrain)
143
164
  .off('timeout', this._ontimeout)
144
165
 
145
- HTTPClientConnection._connections.delete(this.socket)
166
+ HTTPClientConnection._connections.delete(this._socket)
146
167
  }
147
168
  }
@@ -16,38 +16,48 @@ module.exports = class HTTPClientRequest extends HTTPOutgoingMessage {
16
16
  const agent = opts.agent === false ? new HTTPAgent() : opts.agent || HTTPAgent.global
17
17
  const method = opts.method || 'GET'
18
18
  const path = opts.path || '/'
19
+ const defaultPort = opts.defaultPort || (agent && agent.defaultPort) || 80
19
20
  const host = (opts.host = opts.host || 'localhost')
20
- const port = (opts.port = opts.port || 80)
21
- const headers = { host: host + (port === 80 ? '' : ':' + port), ...opts.headers }
21
+ const port = (opts.port = opts.port || defaultPort)
22
+ const headers = { host: hostHeader(host, port, defaultPort), ...opts.headers }
22
23
 
23
24
  super()
24
25
 
25
26
  agent.addRequest(this, opts)
26
27
 
27
- this.method = method
28
- this.path = path
29
- this.headers = headers
28
+ this._headers = headers
29
+ this._method = method
30
+ this._path = path
30
31
 
31
32
  this._chunked = method !== 'GET' && method !== 'HEAD'
32
33
 
34
+ this._pendingWrite = null
33
35
  this._pendingFinal = null
34
36
 
35
37
  if (onresponse) this.once('response', onresponse)
36
38
  }
37
39
 
40
+ get method() {
41
+ return this._method
42
+ }
43
+
44
+ get path() {
45
+ return this._path
46
+ }
47
+
38
48
  // For Node.js compatibility
39
49
  abort() {
40
50
  return this.destroy()
41
51
  }
42
52
 
43
53
  _header() {
44
- let h = `${this.method} ${this.path} HTTP/1.1\r\n`
54
+ let h = `${this._method} ${this._path} HTTP/1.1\r\n`
45
55
 
46
56
  let upgrade = false
47
57
 
48
- for (const name of Object.keys(this.headers)) {
58
+ for (const name of Object.keys(this._headers)) {
49
59
  const n = name.toLowerCase()
50
- const v = this.headers[name]
60
+ const v = this._headers[name]
51
61
 
52
62
  if (n === 'content-length') this._chunked = false
53
63
  if (n === 'connection' && v && v.toLowerCase() === 'upgrade') upgrade = true
@@ -65,33 +75,34 @@ module.exports = class HTTPClientRequest extends HTTPOutgoingMessage {
65
75
  }
66
76
 
67
77
  _write(data, encoding, cb) {
68
- if (this.headersSent === false) this.flushHeaders()
78
+ if (this._headersSent === false) this.flushHeaders()
69
79
 
70
80
  if (this._chunked) {
71
- this.socket.write(Buffer.from(data.byteLength.toString(16)))
72
- this.socket.write(CHUNK_DELIMITER)
81
+ this._socket.write(Buffer.from(data.byteLength.toString(16)))
82
+ this._socket.write(CHUNK_DELIMITER)
73
83
  }
74
84
 
75
- let flushed = this.socket.write(data)
85
+ let flushed = this._socket.write(data)
76
86
 
77
- if (this._chunked) flushed = this.socket.write(CHUNK_DELIMITER)
87
+ if (this._chunked) flushed = this._socket.write(CHUNK_DELIMITER)
78
88
 
79
89
  if (flushed) cb(null)
80
90
  else this._pendingWrite = cb
81
91
  }
82
92
 
83
93
  _final(cb) {
84
- if (this.headersSent === false) this.flushHeaders()
94
+ if (this._headersSent === false) this.flushHeaders()
85
95
 
86
- if (this._chunked) this.socket.write(CHUNK_TERMINATOR)
96
+ if (this._chunked) this._socket.write(CHUNK_TERMINATOR)
87
97
 
88
98
  this._pendingFinal = cb
89
99
  }
90
100
 
91
101
  _predestroy() {
92
- if (this.upgrade) return this._continueFinal()
102
+ super._predestroy()
93
103
 
94
- this.socket.destroy()
104
+ this._continueWrite()
105
+ this._continueFinal()
95
106
  }
96
107
 
97
108
  _continueWrite() {
@@ -116,3 +127,17 @@ function httpCase(n) {
116
127
  }
117
128
  return s
118
129
  }
130
+
131
+ function hostHeader(host, port, defaultPort) {
132
+ const i = host.indexOf(':')
133
+
134
+ if (i !== -1 && host.includes(':', i + 1) && host.charCodeAt(0) !== 91 /* [ */) {
135
+ host = `[${host}]`
136
+ }
137
+
138
+ if (port && +port !== defaultPort) {
139
+ host += ':' + port
140
+ }
141
+
142
+ return host
143
+ }
package/lib/errors.d.ts CHANGED
@@ -1,8 +1,5 @@
1
1
  declare class HTTPError extends Error {
2
- private constructor()
3
-
4
- static NOT_IMPLEMENTED(msg?: string): HTTPError
5
- static CONNECTION_LOST(msg?: string): HTTPError
2
+ readonly code: string
6
3
  }
7
4
 
8
5
  export = HTTPError
package/lib/errors.js CHANGED
@@ -19,4 +19,8 @@ module.exports = class HTTPError extends Error {
19
19
  static CONNECTION_LOST(msg = 'Socket hung up') {
20
20
  return new HTTPError(msg, HTTPError.CONNECTION_LOST)
21
21
  }
22
+
23
+ static AGENT_SUSPENDED(msg = 'Agent is suspended') {
24
+ return new HTTPError(msg, HTTPError.AGENT_SUSPENDED)
25
+ }
22
26
  }
@@ -4,17 +4,45 @@ module.exports = class HTTPIncomingMessage extends Readable {
4
4
  constructor(socket = null, headers = {}, opts = {}) {
5
5
  super()
6
6
 
7
- this.socket = socket
8
- this.headers = headers
9
- this.upgrade = false
7
+ this._socket = socket
8
+ this._headers = headers
9
+ this._upgrade = false
10
10
 
11
11
  // Server options
12
- this.method = opts.method || ''
13
- this.url = opts.url || ''
12
+ this._method = opts.method || ''
13
+ this._url = opts.url || ''
14
14
 
15
15
  // Client options
16
- this.statusCode = opts.statusCode || 0
17
- this.statusMessage = opts.statusMessage || ''
16
+ this._statusCode = opts.statusCode || 0
17
+ this._statusMessage = opts.statusMessage || ''
18
+ }
19
+
20
+ get socket() {
21
+ return this._socket
22
+ }
23
+
24
+ get headers() {
25
+ return this._headers
26
+ }
27
+
28
+ get upgrade() {
29
+ return this._upgrade
30
+ }
31
+
32
+ get method() {
33
+ return this._method
34
+ }
35
+
36
+ get url() {
37
+ return this._url
38
+ }
39
+
40
+ get statusCode() {
41
+ return this._statusCode
42
+ }
43
+
44
+ get statusMessage() {
45
+ return this._statusMessage
18
46
  }
19
47
 
20
48
  get httpVersion() {
@@ -22,26 +50,26 @@ module.exports = class HTTPIncomingMessage extends Readable {
22
50
  }
23
51
 
24
52
  getHeader(name) {
25
- return this.headers[name.toLowerCase()]
53
+ return this._headers[name.toLowerCase()]
26
54
  }
27
55
 
28
56
  getHeaders() {
29
- return { ...this.headers }
57
+ return { ...this._headers }
30
58
  }
31
59
 
32
60
  hasHeader(name) {
33
- return name.toLowerCase() in this.headers
61
+ return name.toLowerCase() in this._headers
34
62
  }
35
63
 
36
64
  setTimeout(ms, ontimeout) {
37
65
  if (ontimeout) this.once('timeout', ontimeout)
38
66
 
39
- this.socket.setTimeout(ms)
67
+ this._socket.setTimeout(ms)
40
68
 
41
69
  return this
42
70
  }
43
71
 
44
72
  _predestroy() {
45
- if (this.upgrade === false && this.socket !== null) this.socket.destroy()
73
+ if (this._upgrade === false && this._socket !== null) this._socket.destroy()
46
74
  }
47
75
  }
@@ -5,39 +5,55 @@ module.exports = class HTTPOutgoingMessage extends Writable {
5
5
  constructor(socket = null) {
6
6
  super()
7
7
 
8
- this.socket = socket
9
- this.headers = {}
10
- this.headersSent = false
11
- this.upgrade = false
8
+ this._socket = socket
9
+ this._headers = {}
10
+ this._headersSent = false
11
+ this._upgrade = false
12
+ }
13
+
14
+ get socket() {
15
+ return this._socket
16
+ }
17
+
18
+ get headers() {
19
+ return this._headers
20
+ }
21
+
22
+ get headersSent() {
23
+ return this._headersSent
24
+ }
25
+
26
+ get upgrade() {
27
+ return this._upgrade
12
28
  }
13
29
 
14
30
  getHeader(name) {
15
- return this.headers[name.toLowerCase()]
31
+ return this._headers[name.toLowerCase()]
16
32
  }
17
33
 
18
34
  getHeaders() {
19
- return { ...this.headers }
35
+ return { ...this._headers }
20
36
  }
21
37
 
22
38
  hasHeader(name) {
23
- return name.toLowerCase() in this.headers
39
+ return name.toLowerCase() in this._headers
24
40
  }
25
41
 
26
42
  setHeader(name, value) {
27
- this.headers[name.toLowerCase()] = value
43
+ this._headers[name.toLowerCase()] = value
28
44
  }
29
45
 
30
46
  flushHeaders() {
31
- if (this.headersSent === true || this.socket === null) return
47
+ if (this._headersSent === true || this._socket === null) return
32
48
 
33
- this.socket.write(Buffer.from(this._header()))
34
- this.headersSent = true
49
+ this._socket.write(Buffer.from(this._header()))
50
+ this._headersSent = true
35
51
  }
36
52
 
37
53
  setTimeout(ms, ontimeout) {
38
54
  if (ontimeout) this.once('timeout', ontimeout)
39
55
 
40
- this.socket.setTimeout(ms)
56
+ this._socket.setTimeout(ms)
41
57
 
42
58
  return this
43
59
  }
@@ -47,6 +63,6 @@ module.exports = class HTTPOutgoingMessage extends Writable {
47
63
  }
48
64
 
49
65
  _predestroy() {
50
- if (this.upgrade === false && this.socket !== null) this.socket.destroy()
66
+ if (this._upgrade === false && this._socket !== null) this._socket.destroy()
51
67
  }
52
68
  }
@@ -19,11 +19,11 @@ module.exports = class HTTPServerConnection {
19
19
  constructor(server, socket, opts = {}) {
20
20
  const { IncomingMessage = HTTPIncomingMessage, ServerResponse = HTTPServerResponse } = opts
21
21
 
22
- this.server = server
23
- this.socket = socket
22
+ this._server = server
23
+ this._socket = socket
24
24
 
25
- this.req = null
26
- this.res = null
25
+ this._req = null
26
+ this._res = null
27
27
 
28
28
  this._IncomingMessage = IncomingMessage
29
29
  this._ServerResponse = ServerResponse
@@ -45,7 +45,23 @@ module.exports = class HTTPServerConnection {
45
45
 
46
46
  HTTPServerConnection._connections.set(socket, this)
47
47
 
48
- if (this.server.timeout) socket.setTimeout(this.server.timeout)
48
+ if (this._server.timeout) socket.setTimeout(this._server.timeout)
49
+ }
50
+
51
+ get server() {
52
+ return this._server
53
+ }
54
+
55
+ get socket() {
56
+ return this._socket
57
+ }
58
+
59
+ get req() {
60
+ return this._req
61
+ }
62
+
63
+ get res() {
64
+ return this._res
49
65
  }
50
66
 
51
67
  get idle() {
@@ -53,10 +69,11 @@ module.exports = class HTTPServerConnection {
53
69
  }
54
70
 
55
71
  _onclose() {
56
- if (this.req && !isEnded(this.req)) this.req.destroy()
57
- if (this.res && !isFinished(this.res)) this.res.destroy()
58
- const err = getStreamError(this.socket)
59
- if (err) this.socket.destroy(err)
72
+ if (this._req && !isEnded(this._req)) this._req.destroy()
73
+ if (this._res && !isFinished(this._res)) this._res.destroy()
74
+
75
+ const err = getStreamError(this._socket)
76
+ if (err) this._socket.destroy(err)
60
77
  }
61
78
 
62
79
  _ondata(data) {
@@ -66,86 +83,92 @@ module.exports = class HTTPServerConnection {
66
83
  for (const op of this._parser.push(data)) {
67
84
  switch (op.type) {
68
85
  case REQUEST:
69
- this.req = new this._IncomingMessage(this.socket, op.headers, {
86
+ this._req = new this._IncomingMessage(this._socket, op.headers, {
70
87
  method: op.method,
71
88
  url: op.url
72
89
  })
73
90
 
74
- this.req.on('close', () => {
75
- this.req = null
91
+ this._req.on('close', () => {
92
+ this._req = null
76
93
 
77
94
  this._idle = true
78
95
 
79
- if (this.server.closing) this.socket.destroy()
96
+ if (this._server.closing) this._socket.destroy()
80
97
  })
81
98
 
82
99
  // Eagerly open the request stream
83
- this.req.resume()
84
- this.req.pause()
100
+ this._req.resume()
101
+ this._req.pause()
85
102
 
86
103
  if (op.headers.connection && op.headers.connection.toLowerCase() === 'upgrade') {
87
104
  return this._onupgrade(this._parser.end())
88
105
  }
89
106
 
90
- this.res = new this._ServerResponse(
91
- this.socket,
92
- this.req,
107
+ this._res = new this._ServerResponse(
108
+ this._socket,
109
+ this._req,
93
110
  op.headers.connection === 'close'
94
111
  )
95
112
 
96
- this.res.on('close', () => {
97
- this.res = null
113
+ this._res.on('close', () => {
114
+ this._res = null
98
115
  })
99
116
 
100
- this.server.emit('request', this.req, this.res)
117
+ this._server.emit('request', this._req, this._res)
101
118
  break
102
119
 
103
120
  case DATA:
104
- this.req.push(op.data)
121
+ this._req.push(op.data)
105
122
  break
106
123
 
107
124
  case END:
108
- if (this.req) this.req.push(null)
125
+ if (this._req) {
126
+ this._req._socket = null
127
+ this._req.push(null)
128
+ }
109
129
  break
110
130
  }
111
131
  }
112
132
  } catch (err) {
113
- this.socket.destroy(err)
133
+ this._socket.destroy(err)
114
134
  }
115
135
  }
116
136
 
117
137
  _onupgrade(data) {
118
- this._ondetach()
138
+ this._detach()
139
+
140
+ const req = this._req
141
+
142
+ req._upgrade = true
119
143
 
120
- const req = this.req
144
+ const upgraded = this._server.emit('upgrade', req, this._socket, data || EMPTY)
121
145
 
122
- req.upgrade = true
123
- req.destroy()
146
+ req.push(null)
124
147
 
125
- this.server.emit('upgrade', req, this.socket, data || EMPTY)
148
+ if (!upgraded) this._socket.destroy()
126
149
  }
127
150
 
128
151
  _ontimeout() {
129
- const reqTimeout = this.req && this.req.emit('timeout')
130
- const resTimeout = this.res && this.res.emit('timeout')
131
- const serverTimeout = this.server.emit('timeout', this.socket)
152
+ const reqTimeout = this._req && this._req.emit('timeout')
153
+ const resTimeout = this._res && this._res.emit('timeout')
154
+ const serverTimeout = this._server.emit('timeout', this._socket)
132
155
 
133
- if (!reqTimeout && !resTimeout && !serverTimeout) this.socket.destroy()
156
+ if (!reqTimeout && !resTimeout && !serverTimeout) this._socket.destroy()
134
157
  }
135
158
 
136
159
  _ondrain() {
137
- if (this.res) this.res._continueWrite()
160
+ if (this._res) this._res._continueWrite()
138
161
  }
139
162
 
140
- _ondetach() {
141
- this.socket
163
+ _detach() {
164
+ this._socket
142
165
  .off('error', noop)
143
166
  .off('close', this._onclose)
144
167
  .off('data', this._ondata)
145
168
  .off('drain', this._ondrain)
146
169
  .off('timeout', this._ontimeout)
147
170
 
148
- HTTPServerConnection._connections.delete(this.socket)
171
+ HTTPServerConnection._connections.delete(this._socket)
149
172
  }
150
173
  }
151
174
 
@@ -8,10 +8,10 @@ module.exports = class HTTPServerResponse extends HTTPOutgoingMessage {
8
8
  constructor(socket, req, close) {
9
9
  super(socket)
10
10
 
11
- this.req = req
11
+ this._req = req
12
12
 
13
- this.statusCode = 200
14
- this.statusMessage = null
13
+ this._statusCode = 200
14
+ this._statusMessage = null
15
15
 
16
16
  this._chunked = true
17
17
  this._close = close
@@ -21,8 +21,21 @@ module.exports = class HTTPServerResponse extends HTTPOutgoingMessage {
21
21
  this._pendingWrite = null
22
22
  }
23
23
 
24
+ get req() {
25
+ return this._req
26
+ }
27
+
28
+ get statusCode() {
29
+ return this._statusCode
30
+ }
31
+
32
+ get statusMessage() {
33
+ return this._statusMessage
34
+ }
35
+
24
36
  end(data) {
25
37
  this._finishing = true
38
+
26
39
  return super.end(data)
27
40
  }
28
41
 
@@ -32,22 +45,23 @@ module.exports = class HTTPServerResponse extends HTTPOutgoingMessage {
32
45
  statusMessage = null
33
46
  }
34
47
 
35
- this.statusCode = statusCode
36
- this.statusMessage = statusMessage || null
37
- if (headers) this.headers = { ...this.headers, ...headers }
48
+ this._statusCode = statusCode
49
+ this._statusMessage = statusMessage || null
50
+
51
+ if (headers) this._headers = { ...this._headers, ...headers }
38
52
  }
39
53
 
40
54
  _header() {
41
55
  let h =
42
56
  'HTTP/1.1 ' +
43
- this.statusCode +
57
+ this._statusCode +
44
58
  ' ' +
45
- (this.statusMessage === null ? constants.status[this.statusCode] : this.statusMessage) +
59
+ (this._statusMessage === null ? constants.status[this._statusCode] : this._statusMessage) +
46
60
  '\r\n'
47
61
 
48
- for (const name of Object.keys(this.headers)) {
62
+ for (const name of Object.keys(this._headers)) {
49
63
  const n = name.toLowerCase()
50
- const v = this.headers[name]
64
+ const v = this._headers[name]
51
65
 
52
66
  if (n === 'content-length') this._chunked = false
53
67
  if (n === 'connection' && v && v.toLowerCase() === 'close') this._close = true
@@ -63,7 +77,7 @@ module.exports = class HTTPServerResponse extends HTTPOutgoingMessage {
63
77
  }
64
78
 
65
79
  _write(data, encoding, cb) {
66
- if (this.headersSent === false) {
80
+ if (this._headersSent === false) {
67
81
  if (this._finishing) {
68
82
  this.setHeader(
69
83
  'Content-Length',
@@ -77,36 +91,36 @@ module.exports = class HTTPServerResponse extends HTTPOutgoingMessage {
77
91
  if (this._onlyHeaders === true) return cb(null)
78
92
 
79
93
  if (this._chunked) {
80
- this.socket.write(Buffer.from(data.byteLength.toString(16)))
81
- this.socket.write(CHUNK_DELIMITER)
94
+ this._socket.write(Buffer.from(data.byteLength.toString(16)))
95
+ this._socket.write(CHUNK_DELIMITER)
82
96
  }
83
97
 
84
- let flushed = this.socket.write(data)
98
+ let flushed = this._socket.write(data)
85
99
 
86
- if (this._chunked) flushed = this.socket.write(CHUNK_DELIMITER)
100
+ if (this._chunked) flushed = this._socket.write(CHUNK_DELIMITER)
87
101
 
88
102
  if (flushed) cb(null)
89
103
  else this._pendingWrite = cb
90
104
  }
91
105
 
92
106
  _final(cb) {
93
- if (this.headersSent === false) {
107
+ if (this._headersSent === false) {
94
108
  this.setHeader('Content-Length', '0')
95
109
  this.flushHeaders()
96
110
  }
97
111
 
98
- if (this._chunked && this._onlyHeaders === false) {
99
- this.socket.write(CHUNK_TERMINATOR)
100
- }
112
+ if (this._chunked && this._onlyHeaders === false) this._socket.write(CHUNK_TERMINATOR)
101
113
 
102
- if (this._close) this.socket.end()
114
+ if (this._close) this._socket.end()
103
115
 
104
116
  cb(null)
105
117
  }
106
118
 
107
119
  _predestroy() {
108
120
  super._predestroy()
109
- this.req.destroy()
121
+
122
+ this._req.destroy()
123
+
110
124
  this._continueWrite()
111
125
  }
112
126
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-http1",
3
- "version": "4.3.1",
3
+ "version": "4.5.1",
4
4
  "description": "Native HTTP/1 library for JavaScript",
5
5
  "exports": {
6
6
  "./package": "./package.json",
@@ -37,7 +37,7 @@
37
37
  "homepage": "https://github.com/holepunchto/bare-http1#readme",
38
38
  "dependencies": {
39
39
  "bare-events": "^2.6.0",
40
- "bare-http-parser": "^1.0.0",
40
+ "bare-http-parser": "^1.1.1",
41
41
  "bare-stream": "^2.3.0",
42
42
  "bare-tcp": "^2.2.0"
43
43
  },