bare-http1 4.3.1 → 4.4.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.
- package/lib/agent.js +17 -15
- package/lib/client-connection.js +43 -29
- package/lib/client-request.js +42 -17
- package/lib/incoming-message.js +40 -12
- package/lib/outgoing-message.js +29 -13
- package/lib/server-connection.js +56 -37
- package/lib/server-response.js +34 -19
- package/package.json +1 -1
package/lib/agent.js
CHANGED
|
@@ -66,12 +66,13 @@ class HTTPAgent extends EventEmitter {
|
|
|
66
66
|
constructor(opts = {}) {
|
|
67
67
|
super()
|
|
68
68
|
|
|
69
|
-
const { keepAlive = false, keepAliveMsecs = 1000 } = opts
|
|
69
|
+
const { keepAlive = false, keepAliveMsecs = 1000, defaultPort = 80 } = opts
|
|
70
70
|
|
|
71
71
|
this._sockets = new HTTPSocketSet()
|
|
72
72
|
this._freeSockets = new HTTPSocketSet()
|
|
73
73
|
|
|
74
74
|
this._keepAlive = typeof keepAlive === 'number' ? keepAlive : keepAlive ? keepAliveMsecs : -1
|
|
75
|
+
this._defaultPort = defaultPort
|
|
75
76
|
|
|
76
77
|
this._opts = { ...opts }
|
|
77
78
|
}
|
|
@@ -84,6 +85,10 @@ class HTTPAgent extends EventEmitter {
|
|
|
84
85
|
return this._freeSockets.sockets()
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
get defaultPort() {
|
|
89
|
+
return this._defaultPort
|
|
90
|
+
}
|
|
91
|
+
|
|
87
92
|
createConnection(opts) {
|
|
88
93
|
return tcp.createConnection(opts)
|
|
89
94
|
}
|
|
@@ -120,10 +125,10 @@ class HTTPAgent extends EventEmitter {
|
|
|
120
125
|
|
|
121
126
|
socket
|
|
122
127
|
.on('free', onfree)
|
|
123
|
-
.on('timeout', ontimeout)
|
|
124
128
|
.on('end', onremove)
|
|
125
129
|
.on('finish', onremove)
|
|
126
130
|
.on('close', onremove)
|
|
131
|
+
.on('timeout', ontimeout)
|
|
127
132
|
|
|
128
133
|
function onfree() {
|
|
129
134
|
if (socket.destroyed) return
|
|
@@ -137,12 +142,6 @@ class HTTPAgent extends EventEmitter {
|
|
|
137
142
|
agent.emit('free', socket)
|
|
138
143
|
}
|
|
139
144
|
|
|
140
|
-
function ontimeout() {
|
|
141
|
-
socket.destroy()
|
|
142
|
-
|
|
143
|
-
agent._freeSockets.delete(name, socket)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
145
|
function onremove() {
|
|
147
146
|
socket.off('free', onfree)
|
|
148
147
|
|
|
@@ -151,30 +150,31 @@ class HTTPAgent extends EventEmitter {
|
|
|
151
150
|
|
|
152
151
|
if (agent._sockets.size === 0) HTTPAgent._agents.delete(agent)
|
|
153
152
|
}
|
|
153
|
+
|
|
154
|
+
function ontimeout() {
|
|
155
|
+
socket.destroy()
|
|
156
|
+
|
|
157
|
+
agent._freeSockets.delete(name, socket)
|
|
158
|
+
}
|
|
154
159
|
}
|
|
155
160
|
|
|
156
161
|
if (this._sockets.size === 0) HTTPAgent._agents.add(this)
|
|
157
162
|
|
|
158
163
|
this._sockets.add(name, socket)
|
|
159
164
|
|
|
160
|
-
req.
|
|
165
|
+
req._socket = socket
|
|
161
166
|
|
|
162
167
|
const connection = HTTPClientConnection.from(socket, opts)
|
|
163
168
|
|
|
164
|
-
connection.
|
|
169
|
+
connection._req = req
|
|
165
170
|
}
|
|
166
171
|
|
|
167
172
|
destroy() {
|
|
168
173
|
for (const socket of this._sockets.sockets()) socket.destroy()
|
|
169
174
|
}
|
|
170
175
|
|
|
171
|
-
static _global = new this({ keepAlive: 1000, timeout: 5000 })
|
|
172
176
|
static _agents = new Set()
|
|
173
177
|
|
|
174
|
-
static get global() {
|
|
175
|
-
return this._global
|
|
176
|
-
}
|
|
177
|
-
|
|
178
178
|
static _onidle() {
|
|
179
179
|
for (const agent of this._agents) {
|
|
180
180
|
for (const socket of agent._sockets.sockets()) socket.destroy()
|
|
@@ -182,6 +182,8 @@ class HTTPAgent extends EventEmitter {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
HTTPAgent.global = new HTTPAgent({ keepAlive: 1000, timeout: 5000 })
|
|
186
|
+
|
|
185
187
|
module.exports = HTTPAgent
|
|
186
188
|
|
|
187
189
|
Bare.on('idle', HTTPAgent._onidle.bind(HTTPAgent))
|
package/lib/client-connection.js
CHANGED
|
@@ -22,10 +22,10 @@ module.exports = class HTTPClientConnection {
|
|
|
22
22
|
constructor(socket, opts = {}) {
|
|
23
23
|
const { IncomingMessage = HTTPIncomingMessage } = opts
|
|
24
24
|
|
|
25
|
-
this.
|
|
25
|
+
this._socket = socket
|
|
26
26
|
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
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.
|
|
70
|
+
if (this._req) this._req.destroy(err)
|
|
59
71
|
}
|
|
60
72
|
|
|
61
73
|
_onclose() {
|
|
62
|
-
if (this.
|
|
74
|
+
if (this._req) this._req._continueFinal()
|
|
63
75
|
}
|
|
64
76
|
|
|
65
77
|
_onend() {
|
|
66
|
-
if (this.
|
|
78
|
+
if (this._req) this._req.destroy(errors.CONNECTION_LOST())
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
_ondata(data) {
|
|
@@ -73,68 +85,70 @@ 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.
|
|
77
|
-
this.
|
|
88
|
+
this._req.on('close', () => {
|
|
89
|
+
this._req = null
|
|
78
90
|
})
|
|
79
91
|
|
|
80
|
-
this.
|
|
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.
|
|
86
|
-
this.
|
|
87
|
-
|
|
97
|
+
this._res.on('close', () => {
|
|
98
|
+
this._res = null
|
|
88
99
|
this._idle = true
|
|
89
100
|
|
|
90
|
-
this.
|
|
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.
|
|
108
|
+
this._req.emit('response', this._res)
|
|
98
109
|
break
|
|
99
110
|
|
|
100
111
|
case DATA:
|
|
101
|
-
this.
|
|
112
|
+
this._res.push(op.data)
|
|
102
113
|
break
|
|
103
114
|
|
|
104
115
|
case END:
|
|
105
|
-
if (this.
|
|
106
|
-
if (this.
|
|
116
|
+
if (this._res) this._res.push(null)
|
|
117
|
+
if (this._req) this._req._continueFinal()
|
|
107
118
|
break
|
|
108
119
|
}
|
|
109
120
|
}
|
|
110
121
|
} catch (err) {
|
|
111
|
-
this.
|
|
122
|
+
this._socket.destroy(err)
|
|
112
123
|
}
|
|
113
124
|
}
|
|
114
125
|
|
|
115
126
|
_onupgrade(data) {
|
|
116
|
-
this.
|
|
127
|
+
this._detach()
|
|
128
|
+
|
|
129
|
+
const res = this._res
|
|
130
|
+
const req = this._req
|
|
117
131
|
|
|
118
|
-
|
|
132
|
+
res._upgrade = req._upgrade = true
|
|
119
133
|
|
|
120
|
-
req.upgrade
|
|
121
|
-
req.destroy()
|
|
134
|
+
const upgraded = req.emit('upgrade', res, this._socket, data || EMPTY)
|
|
122
135
|
|
|
123
|
-
|
|
136
|
+
res.push(null)
|
|
137
|
+
req._continueFinal()
|
|
124
138
|
|
|
125
|
-
this.
|
|
139
|
+
if (!upgraded) this._socket.destroy()
|
|
126
140
|
}
|
|
127
141
|
|
|
128
142
|
_ontimeout() {
|
|
129
|
-
if (this.
|
|
143
|
+
if (this._req) this._req.emit('timeout')
|
|
130
144
|
}
|
|
131
145
|
|
|
132
146
|
_ondrain() {
|
|
133
|
-
if (this.
|
|
147
|
+
if (this._req) this._req._continueWrite()
|
|
134
148
|
}
|
|
135
149
|
|
|
136
|
-
|
|
137
|
-
this.
|
|
150
|
+
_detach() {
|
|
151
|
+
this._socket
|
|
138
152
|
.off('error', this._onerror)
|
|
139
153
|
.off('close', this._onclose)
|
|
140
154
|
.off('end', this._onend)
|
|
@@ -142,6 +156,6 @@ module.exports = class HTTPClientConnection {
|
|
|
142
156
|
.off('drain', this._ondrain)
|
|
143
157
|
.off('timeout', this._ontimeout)
|
|
144
158
|
|
|
145
|
-
HTTPClientConnection._connections.delete(this.
|
|
159
|
+
HTTPClientConnection._connections.delete(this._socket)
|
|
146
160
|
}
|
|
147
161
|
}
|
package/lib/client-request.js
CHANGED
|
@@ -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 ||
|
|
21
|
-
const headers = { host: host
|
|
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.
|
|
28
|
-
this.
|
|
29
|
-
this.
|
|
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.
|
|
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.
|
|
58
|
+
for (const name of Object.keys(this._headers)) {
|
|
49
59
|
const n = name.toLowerCase()
|
|
50
|
-
const v = this.
|
|
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.
|
|
78
|
+
if (this._headersSent === false) this.flushHeaders()
|
|
69
79
|
|
|
70
80
|
if (this._chunked) {
|
|
71
|
-
this.
|
|
72
|
-
this.
|
|
81
|
+
this._socket.write(Buffer.from(data.byteLength.toString(16)))
|
|
82
|
+
this._socket.write(CHUNK_DELIMITER)
|
|
73
83
|
}
|
|
74
84
|
|
|
75
|
-
let flushed = this.
|
|
85
|
+
let flushed = this._socket.write(data)
|
|
76
86
|
|
|
77
|
-
if (this._chunked) flushed = this.
|
|
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.
|
|
94
|
+
if (this._headersSent === false) this.flushHeaders()
|
|
85
95
|
|
|
86
|
-
if (this._chunked) this.
|
|
96
|
+
if (this._chunked) this._socket.write(CHUNK_TERMINATOR)
|
|
87
97
|
|
|
88
98
|
this._pendingFinal = cb
|
|
89
99
|
}
|
|
90
100
|
|
|
91
101
|
_predestroy() {
|
|
92
|
-
|
|
102
|
+
super._predestroy()
|
|
93
103
|
|
|
94
|
-
this.
|
|
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/incoming-message.js
CHANGED
|
@@ -4,17 +4,45 @@ module.exports = class HTTPIncomingMessage extends Readable {
|
|
|
4
4
|
constructor(socket = null, headers = {}, opts = {}) {
|
|
5
5
|
super()
|
|
6
6
|
|
|
7
|
-
this.
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
7
|
+
this._socket = socket
|
|
8
|
+
this._headers = headers
|
|
9
|
+
this._upgrade = false
|
|
10
10
|
|
|
11
11
|
// Server options
|
|
12
|
-
this.
|
|
13
|
-
this.
|
|
12
|
+
this._method = opts.method || ''
|
|
13
|
+
this._url = opts.url || ''
|
|
14
14
|
|
|
15
15
|
// Client options
|
|
16
|
-
this.
|
|
17
|
-
this.
|
|
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.
|
|
53
|
+
return this._headers[name.toLowerCase()]
|
|
26
54
|
}
|
|
27
55
|
|
|
28
56
|
getHeaders() {
|
|
29
|
-
return { ...this.
|
|
57
|
+
return { ...this._headers }
|
|
30
58
|
}
|
|
31
59
|
|
|
32
60
|
hasHeader(name) {
|
|
33
|
-
return name.toLowerCase() in this.
|
|
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.
|
|
67
|
+
this._socket.setTimeout(ms)
|
|
40
68
|
|
|
41
69
|
return this
|
|
42
70
|
}
|
|
43
71
|
|
|
44
72
|
_predestroy() {
|
|
45
|
-
if (this.
|
|
73
|
+
if (this._upgrade === false && this._socket !== null) this._socket.destroy()
|
|
46
74
|
}
|
|
47
75
|
}
|
package/lib/outgoing-message.js
CHANGED
|
@@ -5,39 +5,55 @@ module.exports = class HTTPOutgoingMessage extends Writable {
|
|
|
5
5
|
constructor(socket = null) {
|
|
6
6
|
super()
|
|
7
7
|
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
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.
|
|
31
|
+
return this._headers[name.toLowerCase()]
|
|
16
32
|
}
|
|
17
33
|
|
|
18
34
|
getHeaders() {
|
|
19
|
-
return { ...this.
|
|
35
|
+
return { ...this._headers }
|
|
20
36
|
}
|
|
21
37
|
|
|
22
38
|
hasHeader(name) {
|
|
23
|
-
return name.toLowerCase() in this.
|
|
39
|
+
return name.toLowerCase() in this._headers
|
|
24
40
|
}
|
|
25
41
|
|
|
26
42
|
setHeader(name, value) {
|
|
27
|
-
this.
|
|
43
|
+
this._headers[name.toLowerCase()] = value
|
|
28
44
|
}
|
|
29
45
|
|
|
30
46
|
flushHeaders() {
|
|
31
|
-
if (this.
|
|
47
|
+
if (this._headersSent === true || this._socket === null) return
|
|
32
48
|
|
|
33
|
-
this.
|
|
34
|
-
this.
|
|
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.
|
|
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.
|
|
66
|
+
if (this._upgrade === false && this._socket !== null) this._socket.destroy()
|
|
51
67
|
}
|
|
52
68
|
}
|
package/lib/server-connection.js
CHANGED
|
@@ -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.
|
|
23
|
-
this.
|
|
22
|
+
this._server = server
|
|
23
|
+
this._socket = socket
|
|
24
24
|
|
|
25
|
-
this.
|
|
26
|
-
this.
|
|
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.
|
|
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,10 @@ module.exports = class HTTPServerConnection {
|
|
|
53
69
|
}
|
|
54
70
|
|
|
55
71
|
_onclose() {
|
|
56
|
-
if (this.
|
|
57
|
-
if (this.
|
|
58
|
-
const err = getStreamError(this.
|
|
59
|
-
if (err) this.
|
|
72
|
+
if (this._req && !isEnded(this._req)) this._req.destroy()
|
|
73
|
+
if (this._res && !isFinished(this._res)) this._res.destroy()
|
|
74
|
+
const err = getStreamError(this._socket)
|
|
75
|
+
if (err) this._socket.destroy(err)
|
|
60
76
|
}
|
|
61
77
|
|
|
62
78
|
_ondata(data) {
|
|
@@ -66,86 +82,89 @@ module.exports = class HTTPServerConnection {
|
|
|
66
82
|
for (const op of this._parser.push(data)) {
|
|
67
83
|
switch (op.type) {
|
|
68
84
|
case REQUEST:
|
|
69
|
-
this.
|
|
85
|
+
this._req = new this._IncomingMessage(this._socket, op.headers, {
|
|
70
86
|
method: op.method,
|
|
71
87
|
url: op.url
|
|
72
88
|
})
|
|
73
89
|
|
|
74
|
-
this.
|
|
75
|
-
this.
|
|
90
|
+
this._req.on('close', () => {
|
|
91
|
+
this._req = null
|
|
76
92
|
|
|
77
93
|
this._idle = true
|
|
78
94
|
|
|
79
|
-
if (this.
|
|
95
|
+
if (this._server.closing) this._socket.destroy()
|
|
80
96
|
})
|
|
81
97
|
|
|
82
98
|
// Eagerly open the request stream
|
|
83
|
-
this.
|
|
84
|
-
this.
|
|
99
|
+
this._req.resume()
|
|
100
|
+
this._req.pause()
|
|
85
101
|
|
|
86
102
|
if (op.headers.connection && op.headers.connection.toLowerCase() === 'upgrade') {
|
|
87
103
|
return this._onupgrade(this._parser.end())
|
|
88
104
|
}
|
|
89
105
|
|
|
90
|
-
this.
|
|
91
|
-
this.
|
|
92
|
-
this.
|
|
106
|
+
this._res = new this._ServerResponse(
|
|
107
|
+
this._socket,
|
|
108
|
+
this._req,
|
|
93
109
|
op.headers.connection === 'close'
|
|
94
110
|
)
|
|
95
111
|
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
112
|
+
this._res.on('close', () => {
|
|
113
|
+
this._res = null
|
|
98
114
|
})
|
|
99
115
|
|
|
100
|
-
this.
|
|
116
|
+
this._server.emit('request', this._req, this._res)
|
|
101
117
|
break
|
|
102
118
|
|
|
103
119
|
case DATA:
|
|
104
|
-
this.
|
|
120
|
+
this._req.push(op.data)
|
|
105
121
|
break
|
|
106
122
|
|
|
107
123
|
case END:
|
|
108
|
-
if (this.
|
|
124
|
+
if (this._req) this._req.push(null)
|
|
109
125
|
break
|
|
110
126
|
}
|
|
111
127
|
}
|
|
112
128
|
} catch (err) {
|
|
113
|
-
this.
|
|
129
|
+
this._socket.destroy(err)
|
|
114
130
|
}
|
|
115
131
|
}
|
|
116
132
|
|
|
117
133
|
_onupgrade(data) {
|
|
118
|
-
this.
|
|
134
|
+
this._detach()
|
|
135
|
+
|
|
136
|
+
const req = this._req
|
|
137
|
+
|
|
138
|
+
req._upgrade = true
|
|
119
139
|
|
|
120
|
-
const
|
|
140
|
+
const upgraded = this._server.emit('upgrade', req, this._socket, data || EMPTY)
|
|
121
141
|
|
|
122
|
-
req.
|
|
123
|
-
req.destroy()
|
|
142
|
+
req.push(null)
|
|
124
143
|
|
|
125
|
-
this.
|
|
144
|
+
if (!upgraded) this._socket.destroy()
|
|
126
145
|
}
|
|
127
146
|
|
|
128
147
|
_ontimeout() {
|
|
129
|
-
const reqTimeout = this.
|
|
130
|
-
const resTimeout = this.
|
|
131
|
-
const serverTimeout = this.
|
|
148
|
+
const reqTimeout = this._req && this._req.emit('timeout')
|
|
149
|
+
const resTimeout = this._res && this._res.emit('timeout')
|
|
150
|
+
const serverTimeout = this._server.emit('timeout', this._socket)
|
|
132
151
|
|
|
133
|
-
if (!reqTimeout && !resTimeout && !serverTimeout) this.
|
|
152
|
+
if (!reqTimeout && !resTimeout && !serverTimeout) this._socket.destroy()
|
|
134
153
|
}
|
|
135
154
|
|
|
136
155
|
_ondrain() {
|
|
137
|
-
if (this.
|
|
156
|
+
if (this._res) this._res._continueWrite()
|
|
138
157
|
}
|
|
139
158
|
|
|
140
|
-
|
|
141
|
-
this.
|
|
159
|
+
_detach() {
|
|
160
|
+
this._socket
|
|
142
161
|
.off('error', noop)
|
|
143
162
|
.off('close', this._onclose)
|
|
144
163
|
.off('data', this._ondata)
|
|
145
164
|
.off('drain', this._ondrain)
|
|
146
165
|
.off('timeout', this._ontimeout)
|
|
147
166
|
|
|
148
|
-
HTTPServerConnection._connections.delete(this.
|
|
167
|
+
HTTPServerConnection._connections.delete(this._socket)
|
|
149
168
|
}
|
|
150
169
|
}
|
|
151
170
|
|
package/lib/server-response.js
CHANGED
|
@@ -8,10 +8,10 @@ module.exports = class HTTPServerResponse extends HTTPOutgoingMessage {
|
|
|
8
8
|
constructor(socket, req, close) {
|
|
9
9
|
super(socket)
|
|
10
10
|
|
|
11
|
-
this.
|
|
11
|
+
this._req = req
|
|
12
12
|
|
|
13
|
-
this.
|
|
14
|
-
this.
|
|
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.
|
|
36
|
-
this.
|
|
37
|
-
|
|
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.
|
|
57
|
+
this._statusCode +
|
|
44
58
|
' ' +
|
|
45
|
-
(this.
|
|
59
|
+
(this._statusMessage === null ? constants.status[this._statusCode] : this._statusMessage) +
|
|
46
60
|
'\r\n'
|
|
47
61
|
|
|
48
|
-
for (const name of Object.keys(this.
|
|
62
|
+
for (const name of Object.keys(this._headers)) {
|
|
49
63
|
const n = name.toLowerCase()
|
|
50
|
-
const v = this.
|
|
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.
|
|
80
|
+
if (this._headersSent === false) {
|
|
67
81
|
if (this._finishing) {
|
|
68
82
|
this.setHeader(
|
|
69
83
|
'Content-Length',
|
|
@@ -77,36 +91,37 @@ module.exports = class HTTPServerResponse extends HTTPOutgoingMessage {
|
|
|
77
91
|
if (this._onlyHeaders === true) return cb(null)
|
|
78
92
|
|
|
79
93
|
if (this._chunked) {
|
|
80
|
-
this.
|
|
81
|
-
this.
|
|
94
|
+
this._socket.write(Buffer.from(data.byteLength.toString(16)))
|
|
95
|
+
this._socket.write(CHUNK_DELIMITER)
|
|
82
96
|
}
|
|
83
97
|
|
|
84
|
-
let flushed = this.
|
|
98
|
+
let flushed = this._socket.write(data)
|
|
85
99
|
|
|
86
|
-
if (this._chunked) flushed = this.
|
|
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.
|
|
107
|
+
if (this._headersSent === false) {
|
|
94
108
|
this.setHeader('Content-Length', '0')
|
|
95
109
|
this.flushHeaders()
|
|
96
110
|
}
|
|
97
111
|
|
|
98
112
|
if (this._chunked && this._onlyHeaders === false) {
|
|
99
|
-
this.
|
|
113
|
+
this._socket.write(CHUNK_TERMINATOR)
|
|
100
114
|
}
|
|
101
115
|
|
|
102
|
-
if (this._close) this.
|
|
116
|
+
if (this._close) this._socket.end()
|
|
103
117
|
|
|
104
118
|
cb(null)
|
|
105
119
|
}
|
|
106
120
|
|
|
107
121
|
_predestroy() {
|
|
108
122
|
super._predestroy()
|
|
109
|
-
|
|
123
|
+
|
|
124
|
+
this._req.destroy()
|
|
110
125
|
this._continueWrite()
|
|
111
126
|
}
|
|
112
127
|
|