import { Body, cloneBody, extractContentType, getInstanceBody } from './body' import { Headers as BaseHeaders } from './headers' import { NextURL } from '../next-url' import { notImplemented } from '../utils' export const INTERNALS = Symbol('internal request') class BaseRequest extends Body implements Request { [INTERNALS]: { credentials: RequestCredentials headers: Headers method: string referrer: string redirect: RequestRedirect url: NextURL } constructor(input: BaseRequest | string, init: RequestInit = {}) { const method = init.method?.toUpperCase() ?? 'GET' if ( (method === 'GET' || method === 'HEAD') && (init.body || (input instanceof BaseRequest && getInstanceBody(input))) ) { throw new TypeError('Request with GET/HEAD method cannot have body') } let inputBody: BodyInit | null = null if (init.body) { inputBody = init.body } else if (input instanceof BaseRequest && getInstanceBody(input)) { inputBody = cloneBody(input) } super(inputBody) const headers = new BaseHeaders( init.headers || getProp(input, 'headers') || {} ) if (inputBody !== null) { const contentType = extractContentType(this) if (contentType !== null && !headers.has('Content-Type')) { headers.append('Content-Type', contentType) } } this[INTERNALS] = { credentials: init.credentials || getProp(input, 'credentials') || 'same-origin', headers, method, referrer: init.referrer || 'about:client', redirect: init.redirect || getProp(input, 'redirect') || 'follow', url: new NextURL(typeof input === 'string' ? input : input.url), } } get url() { return this[INTERNALS].url.toString() } get credentials() { return this[INTERNALS].credentials } get method() { return this[INTERNALS].method } get referrer() { return this[INTERNALS].referrer } get headers() { return this[INTERNALS].headers } get redirect() { return this[INTERNALS].redirect } public clone() { return new BaseRequest(this) } get cache() { return notImplemented('Request', 'cache') } get integrity() { return notImplemented('Request', 'integrity') } get keepalive() { return notImplemented('Request', 'keepalive') } get mode() { return notImplemented('Request', 'mode') } get destination() { return notImplemented('Request', 'destination') } get referrerPolicy() { return notImplemented('Request', 'referrerPolicy') } get signal() { return notImplemented('Request', 'signal') } get [Symbol.toStringTag]() { return 'Request' } } export { BaseRequest as Request } function getProp( input: BaseRequest | string, key: K ): BaseRequest[K] | undefined { return input instanceof BaseRequest ? input[key] : undefined }