sam522's picture
node
d4b85c0
raw
history blame
2.59 kB
export interface FetchResponseInit extends ResponseInit {
url?: string
}
export class FetchResponse extends Response {
/**
* Response status codes for responses that cannot have body.
* @see https://fetch.spec.whatwg.org/#statuses
*/
static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]
static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]
static isConfigurableStatusCode(status: number): boolean {
return status >= 200 && status <= 599
}
static isRedirectResponse(status: number): boolean {
return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status)
}
/**
* Returns a boolean indicating whether the given response status
* code represents a response that can have a body.
*/
static isResponseWithBody(status: number): boolean {
return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status)
}
static setUrl(url: string | undefined, response: Response): void {
if (!url) {
return
}
if (response.url != '') {
return
}
Object.defineProperty(response, 'url', {
value: url,
enumerable: true,
configurable: true,
writable: false,
})
}
/**
* Parses the given raw HTTP headers into a Fetch API `Headers` instance.
*/
static parseRawHeaders(rawHeaders: Array<string>): Headers {
const headers = new Headers()
for (let line = 0; line < rawHeaders.length; line += 2) {
headers.append(rawHeaders[line], rawHeaders[line + 1])
}
return headers
}
constructor(body?: BodyInit | null, init: FetchResponseInit = {}) {
const status = init.status ?? 200
const safeStatus = FetchResponse.isConfigurableStatusCode(status)
? status
: 200
const finalBody = FetchResponse.isResponseWithBody(status) ? body : null
super(finalBody, {
...init,
status: safeStatus,
})
if (status !== safeStatus) {
/**
* @note Undici keeps an internal "Symbol(state)" that holds
* the actual value of response status. Update that in Node.js.
*/
const stateSymbol = Object.getOwnPropertySymbols(this).find(
(symbol) => symbol.description === 'state'
)
if (stateSymbol) {
const state = Reflect.get(this, stateSymbol) as object
Reflect.set(state, 'status', status)
} else {
Object.defineProperty(this, 'status', {
value: status,
enumerable: true,
configurable: true,
writable: false,
})
}
}
FetchResponse.setUrl(init.url, this)
}
}