@depup/undici 7.24.3-depup.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/LICENSE +21 -0
- package/README.md +25 -0
- package/changes.json +5 -0
- package/docs/docs/api/Agent.md +84 -0
- package/docs/docs/api/BalancedPool.md +99 -0
- package/docs/docs/api/CacheStorage.md +30 -0
- package/docs/docs/api/CacheStore.md +164 -0
- package/docs/docs/api/Client.md +285 -0
- package/docs/docs/api/ClientStats.md +27 -0
- package/docs/docs/api/Connector.md +115 -0
- package/docs/docs/api/ContentType.md +57 -0
- package/docs/docs/api/Cookies.md +101 -0
- package/docs/docs/api/Debug.md +62 -0
- package/docs/docs/api/DiagnosticsChannel.md +313 -0
- package/docs/docs/api/Dispatcher.md +1392 -0
- package/docs/docs/api/EnvHttpProxyAgent.md +159 -0
- package/docs/docs/api/Errors.md +49 -0
- package/docs/docs/api/EventSource.md +45 -0
- package/docs/docs/api/Fetch.md +52 -0
- package/docs/docs/api/GlobalInstallation.md +91 -0
- package/docs/docs/api/H2CClient.md +263 -0
- package/docs/docs/api/MockAgent.md +603 -0
- package/docs/docs/api/MockCallHistory.md +197 -0
- package/docs/docs/api/MockCallHistoryLog.md +43 -0
- package/docs/docs/api/MockClient.md +81 -0
- package/docs/docs/api/MockErrors.md +12 -0
- package/docs/docs/api/MockPool.md +555 -0
- package/docs/docs/api/Pool.md +84 -0
- package/docs/docs/api/PoolStats.md +35 -0
- package/docs/docs/api/ProxyAgent.md +229 -0
- package/docs/docs/api/RedirectHandler.md +96 -0
- package/docs/docs/api/RetryAgent.md +50 -0
- package/docs/docs/api/RetryHandler.md +118 -0
- package/docs/docs/api/RoundRobinPool.md +145 -0
- package/docs/docs/api/SnapshotAgent.md +616 -0
- package/docs/docs/api/Socks5ProxyAgent.md +274 -0
- package/docs/docs/api/Util.md +25 -0
- package/docs/docs/api/WebSocket.md +141 -0
- package/docs/docs/api/api-lifecycle.md +91 -0
- package/docs/docs/best-practices/client-certificate.md +64 -0
- package/docs/docs/best-practices/crawling.md +58 -0
- package/docs/docs/best-practices/mocking-request.md +190 -0
- package/docs/docs/best-practices/proxy.md +127 -0
- package/docs/docs/best-practices/undici-vs-builtin-fetch.md +137 -0
- package/docs/docs/best-practices/writing-tests.md +20 -0
- package/index-fetch.js +65 -0
- package/index.d.ts +3 -0
- package/index.js +234 -0
- package/lib/api/abort-signal.js +59 -0
- package/lib/api/api-connect.js +110 -0
- package/lib/api/api-pipeline.js +252 -0
- package/lib/api/api-request.js +214 -0
- package/lib/api/api-stream.js +209 -0
- package/lib/api/api-upgrade.js +111 -0
- package/lib/api/index.js +7 -0
- package/lib/api/readable.js +580 -0
- package/lib/cache/memory-cache-store.js +234 -0
- package/lib/cache/sqlite-cache-store.js +461 -0
- package/lib/core/connect.js +137 -0
- package/lib/core/constants.js +143 -0
- package/lib/core/diagnostics.js +225 -0
- package/lib/core/errors.js +477 -0
- package/lib/core/request.js +430 -0
- package/lib/core/socks5-client.js +407 -0
- package/lib/core/socks5-utils.js +203 -0
- package/lib/core/symbols.js +75 -0
- package/lib/core/tree.js +160 -0
- package/lib/core/util.js +972 -0
- package/lib/dispatcher/agent.js +158 -0
- package/lib/dispatcher/balanced-pool.js +219 -0
- package/lib/dispatcher/client-h1.js +1610 -0
- package/lib/dispatcher/client-h2.js +995 -0
- package/lib/dispatcher/client.js +654 -0
- package/lib/dispatcher/dispatcher-base.js +165 -0
- package/lib/dispatcher/dispatcher.js +48 -0
- package/lib/dispatcher/env-http-proxy-agent.js +146 -0
- package/lib/dispatcher/fixed-queue.js +135 -0
- package/lib/dispatcher/h2c-client.js +51 -0
- package/lib/dispatcher/pool-base.js +214 -0
- package/lib/dispatcher/pool.js +118 -0
- package/lib/dispatcher/proxy-agent.js +318 -0
- package/lib/dispatcher/retry-agent.js +35 -0
- package/lib/dispatcher/round-robin-pool.js +137 -0
- package/lib/dispatcher/socks5-proxy-agent.js +249 -0
- package/lib/encoding/index.js +33 -0
- package/lib/global.js +50 -0
- package/lib/handler/cache-handler.js +561 -0
- package/lib/handler/cache-revalidation-handler.js +124 -0
- package/lib/handler/decorator-handler.js +67 -0
- package/lib/handler/deduplication-handler.js +460 -0
- package/lib/handler/redirect-handler.js +238 -0
- package/lib/handler/retry-handler.js +394 -0
- package/lib/handler/unwrap-handler.js +100 -0
- package/lib/handler/wrap-handler.js +105 -0
- package/lib/interceptor/cache.js +495 -0
- package/lib/interceptor/decompress.js +259 -0
- package/lib/interceptor/deduplicate.js +117 -0
- package/lib/interceptor/dns.js +571 -0
- package/lib/interceptor/dump.js +112 -0
- package/lib/interceptor/redirect.js +21 -0
- package/lib/interceptor/response-error.js +95 -0
- package/lib/interceptor/retry.js +19 -0
- package/lib/llhttp/.gitkeep +0 -0
- package/lib/llhttp/constants.d.ts +195 -0
- package/lib/llhttp/constants.js +531 -0
- package/lib/llhttp/llhttp-wasm.js +15 -0
- package/lib/llhttp/llhttp_simd-wasm.js +15 -0
- package/lib/llhttp/utils.d.ts +2 -0
- package/lib/llhttp/utils.js +12 -0
- package/lib/mock/mock-agent.js +232 -0
- package/lib/mock/mock-call-history.js +248 -0
- package/lib/mock/mock-client.js +68 -0
- package/lib/mock/mock-errors.js +29 -0
- package/lib/mock/mock-interceptor.js +209 -0
- package/lib/mock/mock-pool.js +68 -0
- package/lib/mock/mock-symbols.js +31 -0
- package/lib/mock/mock-utils.js +480 -0
- package/lib/mock/pending-interceptors-formatter.js +43 -0
- package/lib/mock/snapshot-agent.js +353 -0
- package/lib/mock/snapshot-recorder.js +588 -0
- package/lib/mock/snapshot-utils.js +158 -0
- package/lib/util/cache.js +407 -0
- package/lib/util/date.js +653 -0
- package/lib/util/promise.js +28 -0
- package/lib/util/runtime-features.js +124 -0
- package/lib/util/stats.js +32 -0
- package/lib/util/timers.js +425 -0
- package/lib/web/cache/cache.js +864 -0
- package/lib/web/cache/cachestorage.js +152 -0
- package/lib/web/cache/util.js +45 -0
- package/lib/web/cookies/constants.js +12 -0
- package/lib/web/cookies/index.js +199 -0
- package/lib/web/cookies/parse.js +322 -0
- package/lib/web/cookies/util.js +282 -0
- package/lib/web/eventsource/eventsource-stream.js +399 -0
- package/lib/web/eventsource/eventsource.js +501 -0
- package/lib/web/eventsource/util.js +29 -0
- package/lib/web/fetch/LICENSE +21 -0
- package/lib/web/fetch/body.js +509 -0
- package/lib/web/fetch/constants.js +131 -0
- package/lib/web/fetch/data-url.js +596 -0
- package/lib/web/fetch/formdata-parser.js +575 -0
- package/lib/web/fetch/formdata.js +259 -0
- package/lib/web/fetch/global.js +40 -0
- package/lib/web/fetch/headers.js +719 -0
- package/lib/web/fetch/index.js +2378 -0
- package/lib/web/fetch/request.js +1115 -0
- package/lib/web/fetch/response.js +641 -0
- package/lib/web/fetch/util.js +1520 -0
- package/lib/web/infra/index.js +229 -0
- package/lib/web/subresource-integrity/Readme.md +9 -0
- package/lib/web/subresource-integrity/subresource-integrity.js +307 -0
- package/lib/web/webidl/index.js +1006 -0
- package/lib/web/websocket/connection.js +329 -0
- package/lib/web/websocket/constants.js +126 -0
- package/lib/web/websocket/events.js +331 -0
- package/lib/web/websocket/frame.js +133 -0
- package/lib/web/websocket/permessage-deflate.js +118 -0
- package/lib/web/websocket/receiver.js +450 -0
- package/lib/web/websocket/sender.js +109 -0
- package/lib/web/websocket/stream/websocketerror.js +104 -0
- package/lib/web/websocket/stream/websocketstream.js +497 -0
- package/lib/web/websocket/util.js +347 -0
- package/lib/web/websocket/websocket.js +739 -0
- package/package.json +163 -0
- package/scripts/strip-comments.js +10 -0
- package/types/README.md +6 -0
- package/types/agent.d.ts +32 -0
- package/types/api.d.ts +43 -0
- package/types/balanced-pool.d.ts +30 -0
- package/types/cache-interceptor.d.ts +179 -0
- package/types/cache.d.ts +36 -0
- package/types/client-stats.d.ts +15 -0
- package/types/client.d.ts +123 -0
- package/types/connector.d.ts +36 -0
- package/types/content-type.d.ts +21 -0
- package/types/cookies.d.ts +30 -0
- package/types/diagnostics-channel.d.ts +74 -0
- package/types/dispatcher.d.ts +279 -0
- package/types/env-http-proxy-agent.d.ts +22 -0
- package/types/errors.d.ts +177 -0
- package/types/eventsource.d.ts +66 -0
- package/types/fetch.d.ts +211 -0
- package/types/formdata.d.ts +108 -0
- package/types/global-dispatcher.d.ts +9 -0
- package/types/global-origin.d.ts +7 -0
- package/types/h2c-client.d.ts +73 -0
- package/types/handlers.d.ts +15 -0
- package/types/header.d.ts +160 -0
- package/types/index.d.ts +91 -0
- package/types/interceptors.d.ts +80 -0
- package/types/mock-agent.d.ts +68 -0
- package/types/mock-call-history.d.ts +111 -0
- package/types/mock-client.d.ts +27 -0
- package/types/mock-errors.d.ts +12 -0
- package/types/mock-interceptor.d.ts +94 -0
- package/types/mock-pool.d.ts +27 -0
- package/types/patch.d.ts +29 -0
- package/types/pool-stats.d.ts +19 -0
- package/types/pool.d.ts +41 -0
- package/types/proxy-agent.d.ts +29 -0
- package/types/readable.d.ts +68 -0
- package/types/retry-agent.d.ts +8 -0
- package/types/retry-handler.d.ts +125 -0
- package/types/round-robin-pool.d.ts +41 -0
- package/types/snapshot-agent.d.ts +109 -0
- package/types/socks5-proxy-agent.d.ts +25 -0
- package/types/util.d.ts +18 -0
- package/types/utility.d.ts +7 -0
- package/types/webidl.d.ts +347 -0
- package/types/websocket.d.ts +188 -0
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
InvalidArgumentError,
|
|
5
|
+
NotSupportedError
|
|
6
|
+
} = require('./errors')
|
|
7
|
+
const assert = require('node:assert')
|
|
8
|
+
const {
|
|
9
|
+
isValidHTTPToken,
|
|
10
|
+
isValidHeaderValue,
|
|
11
|
+
isStream,
|
|
12
|
+
destroy,
|
|
13
|
+
isBuffer,
|
|
14
|
+
isFormDataLike,
|
|
15
|
+
isIterable,
|
|
16
|
+
hasSafeIterator,
|
|
17
|
+
isBlobLike,
|
|
18
|
+
serializePathWithQuery,
|
|
19
|
+
assertRequestHandler,
|
|
20
|
+
getServerName,
|
|
21
|
+
normalizedMethodRecords,
|
|
22
|
+
getProtocolFromUrlString
|
|
23
|
+
} = require('./util')
|
|
24
|
+
const { channels } = require('./diagnostics.js')
|
|
25
|
+
const { headerNameLowerCasedRecord } = require('./constants')
|
|
26
|
+
|
|
27
|
+
// Verifies that a given path is valid does not contain control chars \x00 to \x20
|
|
28
|
+
const invalidPathRegex = /[^\u0021-\u00ff]/
|
|
29
|
+
|
|
30
|
+
const kHandler = Symbol('handler')
|
|
31
|
+
|
|
32
|
+
class Request {
|
|
33
|
+
constructor (origin, {
|
|
34
|
+
path,
|
|
35
|
+
method,
|
|
36
|
+
body,
|
|
37
|
+
headers,
|
|
38
|
+
query,
|
|
39
|
+
idempotent,
|
|
40
|
+
blocking,
|
|
41
|
+
upgrade,
|
|
42
|
+
headersTimeout,
|
|
43
|
+
bodyTimeout,
|
|
44
|
+
reset,
|
|
45
|
+
expectContinue,
|
|
46
|
+
servername,
|
|
47
|
+
throwOnError,
|
|
48
|
+
maxRedirections,
|
|
49
|
+
typeOfService
|
|
50
|
+
}, handler) {
|
|
51
|
+
if (typeof path !== 'string') {
|
|
52
|
+
throw new InvalidArgumentError('path must be a string')
|
|
53
|
+
} else if (
|
|
54
|
+
path[0] !== '/' &&
|
|
55
|
+
!(path.startsWith('http://') || path.startsWith('https://')) &&
|
|
56
|
+
method !== 'CONNECT'
|
|
57
|
+
) {
|
|
58
|
+
throw new InvalidArgumentError('path must be an absolute URL or start with a slash')
|
|
59
|
+
} else if (invalidPathRegex.test(path)) {
|
|
60
|
+
throw new InvalidArgumentError('invalid request path')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (typeof method !== 'string') {
|
|
64
|
+
throw new InvalidArgumentError('method must be a string')
|
|
65
|
+
} else if (normalizedMethodRecords[method] === undefined && !isValidHTTPToken(method)) {
|
|
66
|
+
throw new InvalidArgumentError('invalid request method')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (upgrade && typeof upgrade !== 'string') {
|
|
70
|
+
throw new InvalidArgumentError('upgrade must be a string')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (upgrade && !isValidHeaderValue(upgrade)) {
|
|
74
|
+
throw new InvalidArgumentError('invalid upgrade header')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) {
|
|
78
|
+
throw new InvalidArgumentError('invalid headersTimeout')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) {
|
|
82
|
+
throw new InvalidArgumentError('invalid bodyTimeout')
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (reset != null && typeof reset !== 'boolean') {
|
|
86
|
+
throw new InvalidArgumentError('invalid reset')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (expectContinue != null && typeof expectContinue !== 'boolean') {
|
|
90
|
+
throw new InvalidArgumentError('invalid expectContinue')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (throwOnError != null) {
|
|
94
|
+
throw new InvalidArgumentError('invalid throwOnError')
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (maxRedirections != null && maxRedirections !== 0) {
|
|
98
|
+
throw new InvalidArgumentError('maxRedirections is not supported, use the redirect interceptor')
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (typeOfService != null && (!Number.isInteger(typeOfService) || typeOfService < 0 || typeOfService > 255)) {
|
|
102
|
+
throw new InvalidArgumentError('typeOfService must be an integer between 0 and 255')
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
this.headersTimeout = headersTimeout
|
|
106
|
+
|
|
107
|
+
this.bodyTimeout = bodyTimeout
|
|
108
|
+
|
|
109
|
+
this.method = method
|
|
110
|
+
|
|
111
|
+
this.typeOfService = typeOfService ?? 0
|
|
112
|
+
|
|
113
|
+
this.abort = null
|
|
114
|
+
|
|
115
|
+
if (body == null) {
|
|
116
|
+
this.body = null
|
|
117
|
+
} else if (isStream(body)) {
|
|
118
|
+
this.body = body
|
|
119
|
+
|
|
120
|
+
const rState = this.body._readableState
|
|
121
|
+
if (!rState || !rState.autoDestroy) {
|
|
122
|
+
this.endHandler = function autoDestroy () {
|
|
123
|
+
destroy(this)
|
|
124
|
+
}
|
|
125
|
+
this.body.on('end', this.endHandler)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
this.errorHandler = err => {
|
|
129
|
+
if (this.abort) {
|
|
130
|
+
this.abort(err)
|
|
131
|
+
} else {
|
|
132
|
+
this.error = err
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
this.body.on('error', this.errorHandler)
|
|
136
|
+
} else if (isBuffer(body)) {
|
|
137
|
+
this.body = body.byteLength ? body : null
|
|
138
|
+
} else if (ArrayBuffer.isView(body)) {
|
|
139
|
+
this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null
|
|
140
|
+
} else if (body instanceof ArrayBuffer) {
|
|
141
|
+
this.body = body.byteLength ? Buffer.from(body) : null
|
|
142
|
+
} else if (typeof body === 'string') {
|
|
143
|
+
this.body = body.length ? Buffer.from(body) : null
|
|
144
|
+
} else if (isFormDataLike(body) || isIterable(body) || isBlobLike(body)) {
|
|
145
|
+
this.body = body
|
|
146
|
+
} else {
|
|
147
|
+
throw new InvalidArgumentError('body must be a string, a Buffer, a Readable stream, an iterable, or an async iterable')
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
this.completed = false
|
|
151
|
+
this.aborted = false
|
|
152
|
+
|
|
153
|
+
this.upgrade = upgrade || null
|
|
154
|
+
|
|
155
|
+
this.path = query ? serializePathWithQuery(path, query) : path
|
|
156
|
+
|
|
157
|
+
// TODO: shall we maybe standardize it to an URL object?
|
|
158
|
+
this.origin = origin
|
|
159
|
+
|
|
160
|
+
this.protocol = getProtocolFromUrlString(origin)
|
|
161
|
+
|
|
162
|
+
this.idempotent = idempotent == null
|
|
163
|
+
? method === 'HEAD' || method === 'GET'
|
|
164
|
+
: idempotent
|
|
165
|
+
|
|
166
|
+
this.blocking = blocking ?? this.method !== 'HEAD'
|
|
167
|
+
|
|
168
|
+
this.reset = reset == null ? null : reset
|
|
169
|
+
|
|
170
|
+
this.host = null
|
|
171
|
+
|
|
172
|
+
this.contentLength = null
|
|
173
|
+
|
|
174
|
+
this.contentType = null
|
|
175
|
+
|
|
176
|
+
this.headers = []
|
|
177
|
+
|
|
178
|
+
// Only for H2
|
|
179
|
+
this.expectContinue = expectContinue != null ? expectContinue : false
|
|
180
|
+
|
|
181
|
+
if (Array.isArray(headers)) {
|
|
182
|
+
if (headers.length % 2 !== 0) {
|
|
183
|
+
throw new InvalidArgumentError('headers array must be even')
|
|
184
|
+
}
|
|
185
|
+
for (let i = 0; i < headers.length; i += 2) {
|
|
186
|
+
processHeader(this, headers[i], headers[i + 1])
|
|
187
|
+
}
|
|
188
|
+
} else if (headers && typeof headers === 'object') {
|
|
189
|
+
if (hasSafeIterator(headers)) {
|
|
190
|
+
for (const header of headers) {
|
|
191
|
+
if (!Array.isArray(header) || header.length !== 2) {
|
|
192
|
+
throw new InvalidArgumentError('headers must be in key-value pair format')
|
|
193
|
+
}
|
|
194
|
+
processHeader(this, header[0], header[1])
|
|
195
|
+
}
|
|
196
|
+
} else {
|
|
197
|
+
const keys = Object.keys(headers)
|
|
198
|
+
for (let i = 0; i < keys.length; ++i) {
|
|
199
|
+
processHeader(this, keys[i], headers[keys[i]])
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
} else if (headers != null) {
|
|
203
|
+
throw new InvalidArgumentError('headers must be an object or an array')
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
assertRequestHandler(handler, method, upgrade)
|
|
207
|
+
|
|
208
|
+
this.servername = servername || getServerName(this.host) || null
|
|
209
|
+
|
|
210
|
+
this[kHandler] = handler
|
|
211
|
+
|
|
212
|
+
if (channels.create.hasSubscribers) {
|
|
213
|
+
channels.create.publish({ request: this })
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
onBodySent (chunk) {
|
|
218
|
+
if (channels.bodyChunkSent.hasSubscribers) {
|
|
219
|
+
channels.bodyChunkSent.publish({ request: this, chunk })
|
|
220
|
+
}
|
|
221
|
+
if (this[kHandler].onBodySent) {
|
|
222
|
+
try {
|
|
223
|
+
return this[kHandler].onBodySent(chunk)
|
|
224
|
+
} catch (err) {
|
|
225
|
+
this.abort(err)
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
onRequestSent () {
|
|
231
|
+
if (channels.bodySent.hasSubscribers) {
|
|
232
|
+
channels.bodySent.publish({ request: this })
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (this[kHandler].onRequestSent) {
|
|
236
|
+
try {
|
|
237
|
+
return this[kHandler].onRequestSent()
|
|
238
|
+
} catch (err) {
|
|
239
|
+
this.abort(err)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
onConnect (abort) {
|
|
245
|
+
assert(!this.aborted)
|
|
246
|
+
assert(!this.completed)
|
|
247
|
+
|
|
248
|
+
if (this.error) {
|
|
249
|
+
abort(this.error)
|
|
250
|
+
} else {
|
|
251
|
+
this.abort = abort
|
|
252
|
+
return this[kHandler].onConnect(abort)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
onResponseStarted () {
|
|
257
|
+
return this[kHandler].onResponseStarted?.()
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
onHeaders (statusCode, headers, resume, statusText) {
|
|
261
|
+
assert(!this.aborted)
|
|
262
|
+
assert(!this.completed)
|
|
263
|
+
|
|
264
|
+
if (channels.headers.hasSubscribers) {
|
|
265
|
+
channels.headers.publish({ request: this, response: { statusCode, headers, statusText } })
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
try {
|
|
269
|
+
return this[kHandler].onHeaders(statusCode, headers, resume, statusText)
|
|
270
|
+
} catch (err) {
|
|
271
|
+
this.abort(err)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
onData (chunk) {
|
|
276
|
+
assert(!this.aborted)
|
|
277
|
+
assert(!this.completed)
|
|
278
|
+
|
|
279
|
+
if (channels.bodyChunkReceived.hasSubscribers) {
|
|
280
|
+
channels.bodyChunkReceived.publish({ request: this, chunk })
|
|
281
|
+
}
|
|
282
|
+
try {
|
|
283
|
+
return this[kHandler].onData(chunk)
|
|
284
|
+
} catch (err) {
|
|
285
|
+
this.abort(err)
|
|
286
|
+
return false
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
onUpgrade (statusCode, headers, socket) {
|
|
291
|
+
assert(!this.aborted)
|
|
292
|
+
assert(!this.completed)
|
|
293
|
+
|
|
294
|
+
return this[kHandler].onUpgrade(statusCode, headers, socket)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
onComplete (trailers) {
|
|
298
|
+
this.onFinally()
|
|
299
|
+
|
|
300
|
+
assert(!this.aborted)
|
|
301
|
+
assert(!this.completed)
|
|
302
|
+
|
|
303
|
+
this.completed = true
|
|
304
|
+
if (channels.trailers.hasSubscribers) {
|
|
305
|
+
channels.trailers.publish({ request: this, trailers })
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
try {
|
|
309
|
+
return this[kHandler].onComplete(trailers)
|
|
310
|
+
} catch (err) {
|
|
311
|
+
// TODO (fix): This might be a bad idea?
|
|
312
|
+
this.onError(err)
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
onError (error) {
|
|
317
|
+
this.onFinally()
|
|
318
|
+
|
|
319
|
+
if (channels.error.hasSubscribers) {
|
|
320
|
+
channels.error.publish({ request: this, error })
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (this.aborted) {
|
|
324
|
+
return
|
|
325
|
+
}
|
|
326
|
+
this.aborted = true
|
|
327
|
+
|
|
328
|
+
return this[kHandler].onError(error)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
onFinally () {
|
|
332
|
+
if (this.errorHandler) {
|
|
333
|
+
this.body.off('error', this.errorHandler)
|
|
334
|
+
this.errorHandler = null
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (this.endHandler) {
|
|
338
|
+
this.body.off('end', this.endHandler)
|
|
339
|
+
this.endHandler = null
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
addHeader (key, value) {
|
|
344
|
+
processHeader(this, key, value)
|
|
345
|
+
return this
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function processHeader (request, key, val) {
|
|
350
|
+
if (val && (typeof val === 'object' && !Array.isArray(val))) {
|
|
351
|
+
throw new InvalidArgumentError(`invalid ${key} header`)
|
|
352
|
+
} else if (val === undefined) {
|
|
353
|
+
return
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
let headerName = headerNameLowerCasedRecord[key]
|
|
357
|
+
|
|
358
|
+
if (headerName === undefined) {
|
|
359
|
+
headerName = key.toLowerCase()
|
|
360
|
+
if (headerNameLowerCasedRecord[headerName] === undefined && !isValidHTTPToken(headerName)) {
|
|
361
|
+
throw new InvalidArgumentError('invalid header key')
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (Array.isArray(val)) {
|
|
366
|
+
const arr = []
|
|
367
|
+
for (let i = 0; i < val.length; i++) {
|
|
368
|
+
if (typeof val[i] === 'string') {
|
|
369
|
+
if (!isValidHeaderValue(val[i])) {
|
|
370
|
+
throw new InvalidArgumentError(`invalid ${key} header`)
|
|
371
|
+
}
|
|
372
|
+
arr.push(val[i])
|
|
373
|
+
} else if (val[i] === null) {
|
|
374
|
+
arr.push('')
|
|
375
|
+
} else if (typeof val[i] === 'object') {
|
|
376
|
+
throw new InvalidArgumentError(`invalid ${key} header`)
|
|
377
|
+
} else {
|
|
378
|
+
arr.push(`${val[i]}`)
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
val = arr
|
|
382
|
+
} else if (typeof val === 'string') {
|
|
383
|
+
if (!isValidHeaderValue(val)) {
|
|
384
|
+
throw new InvalidArgumentError(`invalid ${key} header`)
|
|
385
|
+
}
|
|
386
|
+
} else if (val === null) {
|
|
387
|
+
val = ''
|
|
388
|
+
} else {
|
|
389
|
+
val = `${val}`
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
if (headerName === 'host') {
|
|
393
|
+
if (request.host !== null) {
|
|
394
|
+
throw new InvalidArgumentError('duplicate host header')
|
|
395
|
+
}
|
|
396
|
+
if (typeof val !== 'string') {
|
|
397
|
+
throw new InvalidArgumentError('invalid host header')
|
|
398
|
+
}
|
|
399
|
+
// Consumed by Client
|
|
400
|
+
request.host = val
|
|
401
|
+
} else if (headerName === 'content-length') {
|
|
402
|
+
if (request.contentLength !== null) {
|
|
403
|
+
throw new InvalidArgumentError('duplicate content-length header')
|
|
404
|
+
}
|
|
405
|
+
request.contentLength = parseInt(val, 10)
|
|
406
|
+
if (!Number.isFinite(request.contentLength)) {
|
|
407
|
+
throw new InvalidArgumentError('invalid content-length header')
|
|
408
|
+
}
|
|
409
|
+
} else if (request.contentType === null && headerName === 'content-type') {
|
|
410
|
+
request.contentType = val
|
|
411
|
+
request.headers.push(key, val)
|
|
412
|
+
} else if (headerName === 'transfer-encoding' || headerName === 'keep-alive' || headerName === 'upgrade') {
|
|
413
|
+
throw new InvalidArgumentError(`invalid ${headerName} header`)
|
|
414
|
+
} else if (headerName === 'connection') {
|
|
415
|
+
const value = typeof val === 'string' ? val.toLowerCase() : null
|
|
416
|
+
if (value !== 'close' && value !== 'keep-alive') {
|
|
417
|
+
throw new InvalidArgumentError('invalid connection header')
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (value === 'close') {
|
|
421
|
+
request.reset = true
|
|
422
|
+
}
|
|
423
|
+
} else if (headerName === 'expect') {
|
|
424
|
+
throw new NotSupportedError('expect header not supported')
|
|
425
|
+
} else {
|
|
426
|
+
request.headers.push(key, val)
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
module.exports = Request
|