Skip to content

Commit

Permalink
deps: update undici to 5.7.0
Browse files Browse the repository at this point in the history
PR-URL: #43790
Reviewed-By: Filip Skokan <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Michaël Zasso <[email protected]>
Reviewed-By: Mohammed Keyvanzadeh <[email protected]>
Reviewed-By: Robert Nagy <[email protected]>
  • Loading branch information
nodejs-github-bot authored and targos committed Jul 13, 2022
1 parent e076955 commit 7fc075b
Show file tree
Hide file tree
Showing 32 changed files with 2,599 additions and 659 deletions.
9 changes: 8 additions & 1 deletion deps/undici/src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ Implements [fetch](https://fetch.spec.whatwg.org/#fetch-method).
* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
* https://fetch.spec.whatwg.org/#fetch-method

Only supported on Node 16.5+.
Only supported on Node 16.8+.

This is [experimental](https://nodejs.org/api/documentation.html#documentation_stability_index) and is not yet fully compliant with the Fetch Standard.
We plan to ship breaking changes to this feature until it is out of experimental.
Expand Down Expand Up @@ -283,6 +283,13 @@ const headers = await fetch(url)
.then(res => res.headers)
```

However, if you want to get only headers, it might be better to use `HEAD` request method. Usage of this method will obviate the need for consumption or cancelling of the response body. See [MDN - HTTP - HTTP request methods - HEAD](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) for more details.

```js
const headers = await fetch(url, { method: 'HEAD' })
.then(res => res.headers)
```

##### Forbidden and Safelisted Header Names

* https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
Expand Down
10 changes: 6 additions & 4 deletions deps/undici/src/docs/api/Dispatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -461,22 +461,22 @@ Arguments:
* **options** `RequestOptions`
* **callback** `(error: Error | null, data: ResponseData) => void` (optional)

Returns: `void | Promise<ResponseData>` - Only returns a `Promise` if no `callback` argument was passed
Returns: `void | Promise<ResponseData>` - Only returns a `Promise` if no `callback` argument was passed.

#### Parameter: `RequestOptions`

Extends: [`DispatchOptions`](#parameter-dispatchoptions)

* **opaque** `unknown` (optional) - Default: `null` - Used for passing through context to `ResponseData`
* **signal** `AbortSignal | events.EventEmitter | null` (optional) - Default: `null`
* **opaque** `unknown` (optional) - Default: `null` - Used for passing through context to `ResponseData`.
* **signal** `AbortSignal | events.EventEmitter | null` (optional) - Default: `null`.
* **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received.

The `RequestOptions.method` property should not be value `'CONNECT'`.

#### Parameter: `ResponseData`

* **statusCode** `number`
* **headers** `http.IncomingHttpHeaders`
* **headers** `http.IncomingHttpHeaders` - Note that all header keys are lower-cased, e. g. `content-type`.
* **body** `stream.Readable` which also implements [the body mixin from the Fetch Standard](https://fetch.spec.whatwg.org/#body-mixin).
* **trailers** `Record<string, string>` - This object starts out
as empty and will be mutated to contain trailers after `body` has emitted `'end'`.
Expand All @@ -497,6 +497,8 @@ The `RequestOptions.method` property should not be value `'CONNECT'`.

- `dump({ limit: Integer })`, dump the response by reading up to `limit` bytes without killing the socket (optional) - Default: 262144.

Note that body will still be a `Readable` even if it is empty, but attempting to deserialize it with `json()` will result in an exception. Recommended way to ensure there is a body to deserialize is to check if status code is not 204, and `content-type` header starts with `application/json`.

#### Example 1 - Basic GET Request

```js
Expand Down
4 changes: 2 additions & 2 deletions deps/undici/src/docs/api/MockAgent.md
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ agent.disableNetConnect()
agent
.get('https://example.com')
.intercept({ method: 'GET', path: '/' })
.reply(200, '')
.reply(200)

const pendingInterceptors = agent.pendingInterceptors()
// Returns [
Expand Down Expand Up @@ -508,7 +508,7 @@ agent.disableNetConnect()
agent
.get('https://example.com')
.intercept({ method: 'GET', path: '/' })
.reply(200, '')
.reply(200)

agent.assertNoPendingInterceptors()
// Throws an UndiciError with the following message:
Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function makeDispatcher (fn) {
module.exports.setGlobalDispatcher = setGlobalDispatcher
module.exports.getGlobalDispatcher = getGlobalDispatcher

if (nodeMajor > 16 || (nodeMajor === 16 && nodeMinor >= 5)) {
if (nodeMajor > 16 || (nodeMajor === 16 && nodeMinor >= 8)) {
let fetchImpl = null
module.exports.fetch = async function fetch (resource) {
if (!fetchImpl) {
Expand Down
22 changes: 3 additions & 19 deletions deps/undici/src/lib/api/api-connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class ConnectHandler extends AsyncResource {
throw new InvalidArgumentError('invalid callback')
}

const { signal, opaque, responseHeaders, httpTunnel } = opts
const { signal, opaque, responseHeaders } = opts

if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') {
throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget')
Expand All @@ -27,7 +27,6 @@ class ConnectHandler extends AsyncResource {
this.responseHeaders = responseHeaders || null
this.callback = callback
this.abort = null
this.httpTunnel = httpTunnel

addSignal(this, signal)
}
Expand All @@ -41,23 +40,8 @@ class ConnectHandler extends AsyncResource {
this.context = context
}

onHeaders (statusCode) {
// when httpTunnel headers are allowed
if (this.httpTunnel) {
const { callback, opaque } = this
if (statusCode !== 200) {
if (callback) {
this.callback = null
const err = new RequestAbortedError('Proxy response !== 200 when HTTP Tunneling')
queueMicrotask(() => {
this.runInAsyncScope(callback, null, err, { opaque })
})
}
return 1
}
} else {
throw new SocketError('bad connect', null)
}
onHeaders () {
throw new SocketError('bad connect', null)
}

onUpgrade (statusCode, rawHeaders, socket) {
Expand Down
34 changes: 31 additions & 3 deletions deps/undici/src/lib/api/api-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,17 @@ class RequestHandler extends AsyncResource {
}

const parsedHeaders = util.parseHeaders(rawHeaders)
const body = new Readable(resume, abort, parsedHeaders['content-type'])
const contentType = parsedHeaders['content-type']
const body = new Readable(resume, abort, contentType)

this.callback = null
this.res = body
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)

if (callback !== null) {
if (this.throwOnError && statusCode >= 400) {
this.runInAsyncScope(callback, null,
new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)
this.runInAsyncScope(getResolveErrorBodyCallback, null,
{ callback, body, contentType, statusCode, statusMessage, headers }
)
return
}
Expand Down Expand Up @@ -152,6 +153,33 @@ class RequestHandler extends AsyncResource {
}
}

async function getResolveErrorBodyCallback ({ callback, body, contentType, statusCode, statusMessage, headers }) {
if (statusCode === 204 || !contentType) {
body.dump()
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers))
return
}

try {
if (contentType.startsWith('application/json')) {
const payload = await body.json()
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload))
return
}

if (contentType.startsWith('text/')) {
const payload = await body.text()
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload))
return
}
} catch (err) {
// Process in a fallback if error
}

body.dump()
process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers))
}

function request (opts, callback) {
if (callback === undefined) {
return new Promise((resolve, reject) => {
Expand Down
8 changes: 3 additions & 5 deletions deps/undici/src/lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ class Parser {
}
}

if (request.method === 'CONNECT' && statusCode >= 200 && statusCode < 300) {
if (request.method === 'CONNECT') {
assert(client[kRunning] === 1)
this.upgrade = true
return 2
Expand Down Expand Up @@ -889,10 +889,8 @@ function onParserTimeout (parser) {

/* istanbul ignore else */
if (timeoutType === TIMEOUT_HEADERS) {
if (!socket[kWriting]) {
assert(!parser.paused, 'cannot be paused while waiting for headers')
util.destroy(socket, new HeadersTimeoutError())
}
assert(!parser.paused, 'cannot be paused while waiting for headers')
util.destroy(socket, new HeadersTimeoutError())
} else if (timeoutType === TIMEOUT_BODY) {
if (!parser.paused) {
util.destroy(socket, new BodyTimeoutError())
Expand Down
12 changes: 2 additions & 10 deletions deps/undici/src/lib/core/errors.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
'use strict'

class AbortError extends Error {
constructor () {
super('The operation was aborted')
this.code = 'ABORT_ERR'
this.name = 'AbortError'
}
}

class UndiciError extends Error {
constructor (message) {
super(message)
Expand Down Expand Up @@ -57,12 +49,13 @@ class BodyTimeoutError extends UndiciError {
}

class ResponseStatusCodeError extends UndiciError {
constructor (message, statusCode, headers) {
constructor (message, statusCode, headers, body) {
super(message)
Error.captureStackTrace(this, ResponseStatusCodeError)
this.name = 'ResponseStatusCodeError'
this.message = message || 'Response Status Code Error'
this.code = 'UND_ERR_RESPONSE_STATUS_CODE'
this.body = body
this.status = statusCode
this.statusCode = statusCode
this.headers = headers
Expand Down Expand Up @@ -191,7 +184,6 @@ class HTTPParserError extends Error {
}

module.exports = {
AbortError,
HTTPParserError,
UndiciError,
HeadersTimeoutError,
Expand Down
4 changes: 2 additions & 2 deletions deps/undici/src/lib/core/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ class Request {
}

if (util.isFormDataLike(this.body)) {
if (nodeMajor < 16 || (nodeMajor === 16 && nodeMinor < 5)) {
throw new InvalidArgumentError('Form-Data bodies are only supported in node v16.5 and newer.')
if (nodeMajor < 16 || (nodeMajor === 16 && nodeMinor < 8)) {
throw new InvalidArgumentError('Form-Data bodies are only supported in node v16.8 and newer.')
}

if (!extractBody) {
Expand Down
Loading

0 comments on commit 7fc075b

Please sign in to comment.