@@ -16,6 +16,9 @@ import {getSearch} from './utils/get-search.js';
1616
1717const INTERNALS = Symbol ( 'Request internals' ) ;
1818
19+ const forbiddenMethods = new Set ( [ "CONNECT" , "TRACE" , "TRACK" ] ) ;
20+ const normalizedMethods = new Set ( [ "DELETE" , "GET" , "HEAD" , "OPTIONS" , "POST" , "PUT" ] ) ;
21+
1922/**
2023 * Check if `obj` is an instance of Request.
2124 *
@@ -33,15 +36,15 @@ const isRequest = object => {
3336/**
3437 * Request class
3538 * @implements {globalThis.Request}
36- *
39+ *
3740 * @typedef {Object } RequestState
3841 * @property {string } method
3942 * @property {RequestRedirect } redirect
4043 * @property {globalThis.Headers } headers
4144 * @property {RequestCredentials } credentials
4245 * @property {URL } parsedURL
4346 * @property {AbortSignal|null } signal
44- *
47+ *
4548 * @typedef {Object } RequestExtraOptions
4649 * @property {number } [follow]
4750 * @property {boolean } [compress]
@@ -50,15 +53,15 @@ const isRequest = object => {
5053 * @property {Agent } [agent]
5154 * @property {number } [highWaterMark]
5255 * @property {boolean } [insecureHTTPParser]
53- *
56+ *
5457 * @typedef {((url:URL) => import('http').Agent | import('https').Agent) | import('http').Agent | import('https').Agent } Agent
55- *
58+ *
5659 * @typedef {Object } RequestOptions
5760 * @property {string } [method]
5861 * @property {ReadableStream<Uint8Array>|null } [body]
5962 * @property {globalThis.Headers } [headers]
6063 * @property {RequestRedirect } [redirect]
61- *
64+ *
6265 */
6366export default class Request extends Body {
6467 /**
@@ -81,8 +84,13 @@ export default class Request extends Body {
8184
8285
8386
87+ // Normalize method: https://fetch.spec.whatwg.org/#methods
8488 let method = init . method || settings . method || 'GET' ;
85- method = method . toUpperCase ( ) ;
89+ if ( forbiddenMethods . has ( method . toUpperCase ( ) ) ) {
90+ throw new TypeError ( `Failed to construct 'Request': '${ method } ' HTTP method is unsupported.` )
91+ } else if ( normalizedMethods . has ( method . toUpperCase ( ) ) ) {
92+ method = method . toUpperCase ( ) ;
93+ }
8694
8795 const inputBody = init . body != null
8896 ? init . body
@@ -100,7 +108,7 @@ export default class Request extends Body {
100108 } ) ;
101109 const input = settings
102110
103-
111+
104112 const headers = /** @type {globalThis.Headers } */
105113 ( new Headers ( init . headers || input . headers || { } ) ) ;
106114
@@ -121,7 +129,7 @@ export default class Request extends Body {
121129 if ( signal != null && ! isAbortSignal ( signal ) ) {
122130 throw new TypeError ( 'Expected signal to be an instanceof AbortSignal or EventTarget' ) ;
123131 }
124-
132+
125133 if ( ! signal ) {
126134 let AbortControllerConstructor = typeof AbortController != "undefined"
127135 ? AbortController
@@ -180,11 +188,11 @@ export default class Request extends Body {
180188 get destination ( ) {
181189 return ""
182190 }
183-
191+
184192 get integrity ( ) {
185193 return ""
186194 }
187-
195+
188196 /** @type {RequestMode } */
189197 get mode ( ) {
190198 return "cors"
@@ -194,7 +202,7 @@ export default class Request extends Body {
194202 get referrer ( ) {
195203 return ""
196204 }
197-
205+
198206 /** @type {ReferrerPolicy } */
199207 get referrerPolicy ( ) {
200208 return ""
@@ -318,7 +326,7 @@ export const getNodeRequestOptions = request => {
318326 port : parsedURL . port ,
319327 hash : parsedURL . hash ,
320328 search : parsedURL . search ,
321- // @ts -ignore - it does not has a query
329+ // @ts -ignore - it does not has a query
322330 query : parsedURL . query ,
323331 href : parsedURL . href ,
324332 method : request . method ,
0 commit comments