commit
This commit is contained in:
parent
13ec9babde
commit
68f4b60012
1429 changed files with 2481 additions and 272836 deletions
119
node_modules/undici/lib/client.js
generated
vendored
119
node_modules/undici/lib/client.js
generated
vendored
|
@ -1,3 +1,5 @@
|
|||
// @ts-check
|
||||
|
||||
'use strict'
|
||||
|
||||
/* global WebAssembly */
|
||||
|
@ -5,6 +7,7 @@
|
|||
const assert = require('assert')
|
||||
const net = require('net')
|
||||
const util = require('./core/util')
|
||||
const timers = require('./timers')
|
||||
const Request = require('./core/request')
|
||||
const DispatcherBase = require('./dispatcher-base')
|
||||
const {
|
||||
|
@ -18,7 +21,8 @@ const {
|
|||
InformationalError,
|
||||
BodyTimeoutError,
|
||||
HTTPParserError,
|
||||
ResponseExceededMaxSizeError
|
||||
ResponseExceededMaxSizeError,
|
||||
ClientDestroyedError
|
||||
} = require('./core/errors')
|
||||
const buildConnector = require('./core/connect')
|
||||
const {
|
||||
|
@ -65,6 +69,7 @@ const {
|
|||
kLocalAddress,
|
||||
kMaxResponseSize
|
||||
} = require('./core/symbols')
|
||||
const FastBuffer = Buffer[Symbol.species]
|
||||
|
||||
const kClosedResolve = Symbol('kClosedResolve')
|
||||
|
||||
|
@ -83,7 +88,15 @@ try {
|
|||
channels.connected = { hasSubscribers: false }
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {import('../types/client').default}
|
||||
*/
|
||||
class Client extends DispatcherBase {
|
||||
/**
|
||||
*
|
||||
* @param {string|URL} url
|
||||
* @param {import('../types/client').Client.Options} options
|
||||
*/
|
||||
constructor (url, {
|
||||
interceptors,
|
||||
maxHeaderSize,
|
||||
|
@ -107,7 +120,9 @@ class Client extends DispatcherBase {
|
|||
connect,
|
||||
maxRequestsPerClient,
|
||||
localAddress,
|
||||
maxResponseSize
|
||||
maxResponseSize,
|
||||
autoSelectFamily,
|
||||
autoSelectFamilyAttemptTimeout
|
||||
} = {}) {
|
||||
super()
|
||||
|
||||
|
@ -183,12 +198,20 @@ class Client extends DispatcherBase {
|
|||
throw new InvalidArgumentError('maxResponseSize must be a positive number')
|
||||
}
|
||||
|
||||
if (
|
||||
autoSelectFamilyAttemptTimeout != null &&
|
||||
(!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1)
|
||||
) {
|
||||
throw new InvalidArgumentError('autoSelectFamilyAttemptTimeout must be a positive number')
|
||||
}
|
||||
|
||||
if (typeof connect !== 'function') {
|
||||
connect = buildConnector({
|
||||
...tls,
|
||||
maxCachedSessions,
|
||||
socketPath,
|
||||
timeout: connectTimeout,
|
||||
...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined),
|
||||
...connect
|
||||
})
|
||||
}
|
||||
|
@ -210,8 +233,8 @@ class Client extends DispatcherBase {
|
|||
this[kResuming] = 0 // 0, idle, 1, scheduled, 2 resuming
|
||||
this[kNeedDrain] = 0 // 0, idle, 1, scheduled, 2 resuming
|
||||
this[kHostHeader] = `host: ${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}\r\n`
|
||||
this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 30e3
|
||||
this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 30e3
|
||||
this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 300e3
|
||||
this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 300e3
|
||||
this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength
|
||||
this[kMaxRedirections] = maxRedirections
|
||||
this[kMaxRequests] = maxRequestsPerClient
|
||||
|
@ -298,7 +321,7 @@ class Client extends DispatcherBase {
|
|||
async [kClose] () {
|
||||
return new Promise((resolve) => {
|
||||
if (!this[kSize]) {
|
||||
this.destroy(resolve)
|
||||
resolve(null)
|
||||
} else {
|
||||
this[kClosedResolve] = resolve
|
||||
}
|
||||
|
@ -315,6 +338,7 @@ class Client extends DispatcherBase {
|
|||
|
||||
const callback = () => {
|
||||
if (this[kClosedResolve]) {
|
||||
// TODO (fix): Should we error here with ClientDestroyedError?
|
||||
this[kClosedResolve]()
|
||||
this[kClosedResolve] = null
|
||||
}
|
||||
|
@ -337,11 +361,11 @@ const createRedirectInterceptor = require('./interceptor/redirectInterceptor')
|
|||
const EMPTY_BUF = Buffer.alloc(0)
|
||||
|
||||
async function lazyllhttp () {
|
||||
const llhttpWasmData = process.env.JEST_WORKER_ID ? require('./llhttp/llhttp.wasm.js') : undefined
|
||||
const llhttpWasmData = process.env.JEST_WORKER_ID ? require('./llhttp/llhttp-wasm.js') : undefined
|
||||
|
||||
let mod
|
||||
try {
|
||||
mod = await WebAssembly.compile(Buffer.from(require('./llhttp/llhttp_simd.wasm.js'), 'base64'))
|
||||
mod = await WebAssembly.compile(Buffer.from(require('./llhttp/llhttp_simd-wasm.js'), 'base64'))
|
||||
} catch (e) {
|
||||
/* istanbul ignore next */
|
||||
|
||||
|
@ -349,7 +373,7 @@ async function lazyllhttp () {
|
|||
// being enabled, but the occurring of this other error
|
||||
// * https://github.com/emscripten-core/emscripten/issues/11495
|
||||
// got me to remove that check to avoid breaking Node 12.
|
||||
mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || require('./llhttp/llhttp.wasm.js'), 'base64'))
|
||||
mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || require('./llhttp/llhttp-wasm.js'), 'base64'))
|
||||
}
|
||||
|
||||
return await WebAssembly.instantiate(mod, {
|
||||
|
@ -362,9 +386,8 @@ async function lazyllhttp () {
|
|||
},
|
||||
wasm_on_status: (p, at, len) => {
|
||||
assert.strictEqual(currentParser.ptr, p)
|
||||
const start = at - currentBufferPtr
|
||||
const end = start + len
|
||||
return currentParser.onStatus(currentBufferRef.slice(start, end)) || 0
|
||||
const start = at - currentBufferPtr + currentBufferRef.byteOffset
|
||||
return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
|
||||
},
|
||||
wasm_on_message_begin: (p) => {
|
||||
assert.strictEqual(currentParser.ptr, p)
|
||||
|
@ -372,15 +395,13 @@ async function lazyllhttp () {
|
|||
},
|
||||
wasm_on_header_field: (p, at, len) => {
|
||||
assert.strictEqual(currentParser.ptr, p)
|
||||
const start = at - currentBufferPtr
|
||||
const end = start + len
|
||||
return currentParser.onHeaderField(currentBufferRef.slice(start, end)) || 0
|
||||
const start = at - currentBufferPtr + currentBufferRef.byteOffset
|
||||
return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
|
||||
},
|
||||
wasm_on_header_value: (p, at, len) => {
|
||||
assert.strictEqual(currentParser.ptr, p)
|
||||
const start = at - currentBufferPtr
|
||||
const end = start + len
|
||||
return currentParser.onHeaderValue(currentBufferRef.slice(start, end)) || 0
|
||||
const start = at - currentBufferPtr + currentBufferRef.byteOffset
|
||||
return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
|
||||
},
|
||||
wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => {
|
||||
assert.strictEqual(currentParser.ptr, p)
|
||||
|
@ -388,9 +409,8 @@ async function lazyllhttp () {
|
|||
},
|
||||
wasm_on_body: (p, at, len) => {
|
||||
assert.strictEqual(currentParser.ptr, p)
|
||||
const start = at - currentBufferPtr
|
||||
const end = start + len
|
||||
return currentParser.onBody(currentBufferRef.slice(start, end)) || 0
|
||||
const start = at - currentBufferPtr + currentBufferRef.byteOffset
|
||||
return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0
|
||||
},
|
||||
wasm_on_message_complete: (p) => {
|
||||
assert.strictEqual(currentParser.ptr, p)
|
||||
|
@ -447,9 +467,9 @@ class Parser {
|
|||
setTimeout (value, type) {
|
||||
this.timeoutType = type
|
||||
if (value !== this.timeoutValue) {
|
||||
clearTimeout(this.timeout)
|
||||
timers.clearTimeout(this.timeout)
|
||||
if (value) {
|
||||
this.timeout = setTimeout(onParserTimeout, value, this)
|
||||
this.timeout = timers.setTimeout(onParserTimeout, value, this)
|
||||
// istanbul ignore else: only for jest
|
||||
if (this.timeout.unref) {
|
||||
this.timeout.unref()
|
||||
|
@ -549,7 +569,10 @@ class Parser {
|
|||
/* istanbul ignore else: difficult to make a test case for */
|
||||
if (ptr) {
|
||||
const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0)
|
||||
message = Buffer.from(llhttp.memory.buffer, ptr, len).toString()
|
||||
message =
|
||||
'Response does not match the HTTP/1.1 protocol (' +
|
||||
Buffer.from(llhttp.memory.buffer, ptr, len).toString() +
|
||||
')'
|
||||
}
|
||||
throw new HTTPParserError(message, constants.ERROR[ret], data.slice(offset))
|
||||
}
|
||||
|
@ -565,7 +588,7 @@ class Parser {
|
|||
this.llhttp.llhttp_free(this.ptr)
|
||||
this.ptr = null
|
||||
|
||||
clearTimeout(this.timeout)
|
||||
timers.clearTimeout(this.timeout)
|
||||
this.timeout = null
|
||||
this.timeoutValue = null
|
||||
this.timeoutType = null
|
||||
|
@ -1064,6 +1087,11 @@ async function connect (client) {
|
|||
})
|
||||
})
|
||||
|
||||
if (client.destroyed) {
|
||||
util.destroy(socket.on('error', () => {}), new ClientDestroyedError())
|
||||
return
|
||||
}
|
||||
|
||||
if (!llhttpInstance) {
|
||||
llhttpInstance = await llhttpPromise
|
||||
llhttpPromise = null
|
||||
|
@ -1106,6 +1134,10 @@ async function connect (client) {
|
|||
}
|
||||
client.emit('connect', client[kUrl], [client])
|
||||
} catch (err) {
|
||||
if (client.destroyed) {
|
||||
return
|
||||
}
|
||||
|
||||
client[kConnecting] = false
|
||||
|
||||
if (channels.connectError.hasSubscribers) {
|
||||
|
@ -1168,8 +1200,9 @@ function _resume (client, sync) {
|
|||
return
|
||||
}
|
||||
|
||||
if (client.closed && !client[kSize]) {
|
||||
client.destroy()
|
||||
if (client[kClosedResolve] && !client[kSize]) {
|
||||
client[kClosedResolve]()
|
||||
client[kClosedResolve] = null
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1421,17 +1454,17 @@ function write (client, request) {
|
|||
/* istanbul ignore else: assertion */
|
||||
if (!body) {
|
||||
if (contentLength === 0) {
|
||||
socket.write(`${header}content-length: 0\r\n\r\n`, 'ascii')
|
||||
socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1')
|
||||
} else {
|
||||
assert(contentLength === null, 'no body must not have content length')
|
||||
socket.write(`${header}\r\n`, 'ascii')
|
||||
socket.write(`${header}\r\n`, 'latin1')
|
||||
}
|
||||
request.onRequestSent()
|
||||
} else if (util.isBuffer(body)) {
|
||||
assert(contentLength === body.byteLength, 'buffer body must have content length')
|
||||
|
||||
socket.cork()
|
||||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii')
|
||||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1')
|
||||
socket.write(body)
|
||||
socket.uncork()
|
||||
request.onBodySent(body)
|
||||
|
@ -1464,9 +1497,11 @@ function writeStream ({ body, client, request, socket, contentLength, header, ex
|
|||
const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header })
|
||||
|
||||
const onData = function (chunk) {
|
||||
try {
|
||||
assert(!finished)
|
||||
if (finished) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if (!writer.write(chunk) && this.pause) {
|
||||
this.pause()
|
||||
}
|
||||
|
@ -1475,7 +1510,9 @@ function writeStream ({ body, client, request, socket, contentLength, header, ex
|
|||
}
|
||||
}
|
||||
const onDrain = function () {
|
||||
assert(!finished)
|
||||
if (finished) {
|
||||
return
|
||||
}
|
||||
|
||||
if (body.resume) {
|
||||
body.resume()
|
||||
|
@ -1546,7 +1583,7 @@ async function writeBlob ({ body, client, request, socket, contentLength, header
|
|||
const buffer = Buffer.from(await body.arrayBuffer())
|
||||
|
||||
socket.cork()
|
||||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii')
|
||||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1')
|
||||
socket.write(buffer)
|
||||
socket.uncork()
|
||||
|
||||
|
@ -1650,26 +1687,30 @@ class AsyncWriter {
|
|||
process.emitWarning(new RequestContentLengthMismatchError())
|
||||
}
|
||||
|
||||
socket.cork()
|
||||
|
||||
if (bytesWritten === 0) {
|
||||
if (!expectsPayload) {
|
||||
socket[kReset] = true
|
||||
}
|
||||
|
||||
if (contentLength === null) {
|
||||
socket.write(`${header}transfer-encoding: chunked\r\n`, 'ascii')
|
||||
socket.write(`${header}transfer-encoding: chunked\r\n`, 'latin1')
|
||||
} else {
|
||||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii')
|
||||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1')
|
||||
}
|
||||
}
|
||||
|
||||
if (contentLength === null) {
|
||||
socket.write(`\r\n${len.toString(16)}\r\n`, 'ascii')
|
||||
socket.write(`\r\n${len.toString(16)}\r\n`, 'latin1')
|
||||
}
|
||||
|
||||
this.bytesWritten += len
|
||||
|
||||
const ret = socket.write(chunk)
|
||||
|
||||
socket.uncork()
|
||||
|
||||
request.onBodySent(chunk)
|
||||
|
||||
if (!ret) {
|
||||
|
@ -1705,12 +1746,12 @@ class AsyncWriter {
|
|||
// no Transfer-Encoding is sent and the request method defines a meaning
|
||||
// for an enclosed payload body.
|
||||
|
||||
socket.write(`${header}content-length: 0\r\n\r\n`, 'ascii')
|
||||
socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1')
|
||||
} else {
|
||||
socket.write(`${header}\r\n`, 'ascii')
|
||||
socket.write(`${header}\r\n`, 'latin1')
|
||||
}
|
||||
} else if (contentLength === null) {
|
||||
socket.write('\r\n0\r\n\r\n', 'ascii')
|
||||
socket.write('\r\n0\r\n\r\n', 'latin1')
|
||||
}
|
||||
|
||||
if (contentLength !== null && bytesWritten !== contentLength) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue