perf: optimization of request instantiation by tsctx · Pull Request #3107 · nodejs/undici · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
7 changes: 4 additions & 3 deletions lib/core/request.js
21 changes: 21 additions & 0 deletions lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,26 @@ function errorRequest (client, request, err) {
const kEnumerableProperty = Object.create(null)
kEnumerableProperty.enumerable = true

const normalizeMethodRecord = {
Comment thread
tsctx marked this conversation as resolved.
Outdated
delete: 'DELETE',
DELETE: 'DELETE',
get: 'GET',
GET: 'GET',
head: 'HEAD',
HEAD: 'HEAD',
options: 'OPTIONS',
OPTIONS: 'OPTIONS',
post: 'POST',
POST: 'POST',
put: 'PUT',
PUT: 'PUT',
patch: 'patch',
PATCH: 'PATCH'
}

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

Comment thread
tsctx marked this conversation as resolved.
module.exports = {
kEnumerableProperty,
nop,
Expand Down Expand Up @@ -600,6 +620,7 @@ module.exports = {
isValidHeaderChar,
isTokenCharCode,
parseRangeHeader,
normalizeMethodRecord,
nodeMajor,
nodeMinor,
nodeHasAutoSelectFamily: nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 13),
Expand Down
34 changes: 8 additions & 26 deletions lib/web/fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@ const { FinalizationRegistry } = require('./dispatcher-weakref')()
const util = require('../../core/util')
const nodeUtil = require('node:util')
const {
isValidHTTPToken,
sameOrigin,
normalizeMethod,
makePolicyContainer,
normalizeMethodRecord
validateAndNormalizeMethod
} = require('./util')
const {
forbiddenMethodsSet,
corsSafeListedMethodsSet,
referrerPolicy,
requestRedirect,
Expand All @@ -24,7 +21,7 @@ const {
requestCache,
requestDuplex
} = require('./constants')
const { kEnumerableProperty } = util
const { kEnumerableProperty, normalizeMethodRecord } = util
const { kHeaders, kSignal, kState, kGuard, kRealm, kDispatcher } = require('./symbols')
const { webidl } = require('./webidl')
const { getGlobalOrigin } = require('./global')
Expand Down Expand Up @@ -318,30 +315,15 @@ class Request {
// 25. If init["method"] exists, then:
if (init.method !== undefined) {
// 1. Let method be init["method"].
let method = init.method
const method = init.method

const mayBeNormalized = normalizeMethodRecord[method]
// 2. If method is not a method or method is a forbidden method, then
// throw a TypeError.

if (mayBeNormalized !== undefined) {
// Note: Bypass validation DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH and these lowercase ones
request.method = mayBeNormalized
} else {
// 2. If method is not a method or method is a forbidden method, then
// throw a TypeError.
if (!isValidHTTPToken(method)) {
throw new TypeError(`'${method}' is not a valid HTTP method.`)
}

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

// 3. Normalize method.
method = normalizeMethod(method)
// 3. Normalize method.

// 4. Set request’s method to method.
request.method = method
}
// 4. Set request’s method to method.
request.method = normalizeMethodRecord[method] ?? validateAndNormalizeMethod(method)

if (!patchMethodWarning && request.method === 'patch') {
process.emitWarning('Using `patch` is highly likely to result in a `405 Method Not Allowed`. `PATCH` is much more likely to succeed.', {
Expand Down
47 changes: 16 additions & 31 deletions lib/web/fetch/util.js