Skip to content

Commit a33056c

Browse files
committed
perf: bypass method validation
1 parent 1ac61d4 commit a33056c

File tree

2 files changed

+29
-14
lines changed

2 files changed

+29
-14
lines changed

lib/fetch/request.js

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -313,21 +313,28 @@ class Request {
313313
// 1. Let method be init["method"].
314314
let method = init.method
315315

316-
// 2. If method is not a method or method is a forbidden method, then
317-
// throw a TypeError.
318-
if (!isValidHTTPToken(method)) {
319-
throw new TypeError(`'${method}' is not a valid HTTP method.`)
320-
}
316+
const mayBeNormalized = normalizeMethodRecord[method]
321317

322-
if (forbiddenMethodsSet.has(method.toUpperCase())) {
323-
throw new TypeError(`'${method}' HTTP method is unsupported.`)
324-
}
318+
if (mayBeNormalized !== undefined) {
319+
// Note: Bypass validation DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH and these lowercase ones
320+
request.method = mayBeNormalized
321+
} else {
322+
// 2. If method is not a method or method is a forbidden method, then
323+
// throw a TypeError.
324+
if (!isValidHTTPToken(method)) {
325+
throw new TypeError(`'${method}' is not a valid HTTP method.`)
326+
}
325327

326-
// 3. Normalize method.
327-
method = normalizeMethodRecord[method] ?? normalizeMethod(method)
328+
if (forbiddenMethodsSet.has(method.toUpperCase())) {
329+
throw new TypeError(`'${method}' HTTP method is unsupported.`)
330+
}
331+
332+
// 3. Normalize method.
333+
method = normalizeMethod(method)
328334

329-
// 4. Set request’s method to method.
330-
request.method = method
335+
// 4. Set request’s method to method.
336+
request.method = method
337+
}
331338
}
332339

333340
// 26. If init["signal"] exists, then set signal to it.

lib/fetch/util.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ function isCancelled (fetchParams) {
681681
fetchParams.controller.state === 'terminated'
682682
}
683683

684-
const normalizeMethodRecord = {
684+
const normalizeMethodRecordBase = {
685685
delete: 'DELETE',
686686
DELETE: 'DELETE',
687687
get: 'GET',
@@ -696,15 +696,22 @@ const normalizeMethodRecord = {
696696
PUT: 'PUT'
697697
}
698698

699+
const normalizeMethodRecord = {
700+
...normalizeMethodRecordBase,
701+
patch: 'patch',
702+
PATCH: 'PATCH'
703+
}
704+
699705
// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`.
706+
Object.setPrototypeOf(normalizeMethodRecordBase, null)
700707
Object.setPrototypeOf(normalizeMethodRecord, null)
701708

702709
/**
703710
* @see https://fetch.spec.whatwg.org/#concept-method-normalize
704711
* @param {string} method
705712
*/
706713
function normalizeMethod (method) {
707-
return normalizeMethodRecord[method.toLowerCase()] ?? method
714+
return normalizeMethodRecordBase[method.toLowerCase()] ?? method
708715
}
709716

710717
// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string
@@ -1211,6 +1218,7 @@ module.exports = {
12111218
urlHasHttpsScheme,
12121219
urlIsHttpHttpsScheme,
12131220
readAllBytes,
1221+
normalizeMethodRecordBase,
12141222
normalizeMethodRecord,
12151223
simpleRangeHeaderValue,
12161224
buildContentRange,

0 commit comments

Comments
 (0)