Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 12 additions & 19 deletions deps/undici/src/lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -917,11 +917,9 @@ class Parser {
socket[kReset] = true
}

let pause
try {
pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false
} catch (err) {
util.destroy(socket, err)
const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false

if (request.aborted) {
return -1
}

Expand Down Expand Up @@ -968,13 +966,8 @@ class Parser {

this.bytesRead += buf.length

try {
if (request.onData(buf) === false) {
return constants.ERROR.PAUSED
}
} catch (err) {
util.destroy(socket, err)
return -1
if (request.onData(buf) === false) {
return constants.ERROR.PAUSED
}
}

Expand Down Expand Up @@ -1015,11 +1008,7 @@ class Parser {
return -1
}

try {
request.onComplete(headers)
} catch (err) {
errorRequest(client, request, err)
}
request.onComplete(headers)

client[kQueue][client[kRunningIdx]++] = null

Expand Down Expand Up @@ -1805,13 +1794,17 @@ function writeH2 (client, session, request) {
})

stream.on('data', (chunk) => {
if (request.onData(chunk) === false) stream.pause()
if (request.onData(chunk) === false) {
stream.pause()
}
})

stream.once('close', () => {
h2State.openStreams -= 1
// TODO(HTTP/2): unref only if current streams count is 0
if (h2State.openStreams === 0) session.unref()
if (h2State.openStreams === 0) {
session.unref()
}
})

stream.once('error', function (err) {
Expand Down
34 changes: 29 additions & 5 deletions deps/undici/src/lib/core/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,11 @@ class Request {

onBodySent (chunk) {
if (this[kHandler].onBodySent) {
return this[kHandler].onBodySent(chunk)
try {
return this[kHandler].onBodySent(chunk)
} catch (err) {
this.abort(err)
}
}
}

Expand All @@ -239,7 +243,11 @@ class Request {
}

if (this[kHandler].onRequestSent) {
return this[kHandler].onRequestSent()
try {
return this[kHandler].onRequestSent()
} catch (err) {
this.abort(err)
}
}
}

Expand All @@ -263,14 +271,23 @@ class Request {
channels.headers.publish({ request: this, response: { statusCode, headers, statusText } })
}

return this[kHandler].onHeaders(statusCode, headers, resume, statusText)
try {
return this[kHandler].onHeaders(statusCode, headers, resume, statusText)
} catch (err) {
this.abort(err)
}
}

onData (chunk) {
assert(!this.aborted)
assert(!this.completed)

return this[kHandler].onData(chunk)
try {
return this[kHandler].onData(chunk)
} catch (err) {
this.abort(err)
return false
}
}

onUpgrade (statusCode, headers, socket) {
Expand All @@ -289,7 +306,13 @@ class Request {
if (channels.trailers.hasSubscribers) {
channels.trailers.publish({ request: this, trailers })
}
return this[kHandler].onComplete(trailers)

try {
return this[kHandler].onComplete(trailers)
} catch (err) {
// TODO (fix): This might be a bad idea?
this.onError(err)
}
}

onError (error) {
Expand All @@ -303,6 +326,7 @@ class Request {
return
}
this.aborted = true

return this[kHandler].onError(error)
}

Expand Down
33 changes: 18 additions & 15 deletions deps/undici/src/lib/fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ const {
isValidHTTPToken,
sameOrigin,
normalizeMethod,
makePolicyContainer
makePolicyContainer,
normalizeMethodRecord
} = require('./util')
const {
forbiddenMethodsSet,
Expand Down Expand Up @@ -183,8 +184,10 @@ class Request {
urlList: [...request.urlList]
})

const initHasKey = Object.keys(init).length !== 0

// 13. If init is not empty, then:
if (Object.keys(init).length > 0) {
if (initHasKey) {
// 1. If request’s mode is "navigate", then set it to "same-origin".
if (request.mode === 'navigate') {
request.mode = 'same-origin'
Expand Down Expand Up @@ -315,16 +318,16 @@ class Request {

// 2. If method is not a method or method is a forbidden method, then
// throw a TypeError.
if (!isValidHTTPToken(init.method)) {
throw new TypeError(`'${init.method}' is not a valid HTTP method.`)
if (!isValidHTTPToken(method)) {
throw new TypeError(`'${method}' is not a valid HTTP method.`)
}

if (forbiddenMethodsSet.has(method.toUpperCase())) {
throw new TypeError(`'${init.method}' HTTP method is unsupported.`)
throw new TypeError(`'${method}' HTTP method is unsupported.`)
}

// 3. Normalize method.
method = normalizeMethod(init.method)
method = normalizeMethodRecord[method] ?? normalizeMethod(method)

// 4. Set request’s method to method.
request.method = method
Expand Down Expand Up @@ -415,25 +418,25 @@ class Request {
}

// 32. If init is not empty, then:
if (Object.keys(init).length !== 0) {
if (initHasKey) {
/** @type {HeadersList} */
const headersList = this[kHeaders][kHeadersList]
// 1. Let headers be a copy of this’s headers and its associated header
// list.
let headers = new Headers(this[kHeaders])

// 2. If init["headers"] exists, then set headers to init["headers"].
if (init.headers !== undefined) {
headers = init.headers
}
const headers = init.headers !== undefined ? init.headers : new HeadersList(headersList)

// 3. Empty this’s headers’s header list.
this[kHeaders][kHeadersList].clear()
headersList.clear()

// 4. If headers is a Headers object, then for each header in its header
// list, append header’s name/header’s value to this’s headers.
if (headers.constructor.name === 'Headers') {
if (headers instanceof HeadersList) {
for (const [key, val] of headers) {
this[kHeaders].append(key, val)
headersList.append(key, val)
}
// Note: Copy the `set-cookie` meta-data.
headersList.cookies = headers.cookies
} else {
// 5. Otherwise, fill this’s headers with headers.
fillHeaders(this[kHeaders], headers)
Expand Down
30 changes: 25 additions & 5 deletions deps/undici/src/lib/fetch/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -698,11 +698,30 @@ function isCancelled (fetchParams) {
fetchParams.controller.state === 'terminated'
}

// https://fetch.spec.whatwg.org/#concept-method-normalize
const normalizeMethodRecord = {
delete: 'DELETE',
DELETE: 'DELETE',
get: 'GET',
GET: 'GET',
head: 'HEAD',
HEAD: 'HEAD',
options: 'OPTIONS',
OPTIONS: 'OPTIONS',
post: 'POST',
POST: 'POST',
put: 'PUT',
PUT: 'PUT'
}

// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`.
Object.setPrototypeOf(normalizeMethodRecord, null)

/**
* @see https://fetch.spec.whatwg.org/#concept-method-normalize
* @param {string} method
*/
function normalizeMethod (method) {
return /^(DELETE|GET|HEAD|OPTIONS|POST|PUT)$/i.test(method)
? method.toUpperCase()
: method
return normalizeMethodRecord[method.toLowerCase()] ?? method
}

// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string
Expand Down Expand Up @@ -1047,5 +1066,6 @@ module.exports = {
urlIsLocal,
urlHasHttpsScheme,
urlIsHttpHttpsScheme,
readAllBytes
readAllBytes,
normalizeMethodRecord
}
Loading