import { getValueBySymbol } from './getValueBySymbol' import { isObject } from './isObject' type RawHeadersMap = Map type HeadersMapHeader = { name: string; value: string } /** * Returns raw headers from the given `Headers` instance. * @example * const headers = new Headers([ * ['X-HeadeR-NamE', 'Value'] * ]) * getRawFetchHeaders(headers) * // { 'X-HeadeR-NamE': 'Value' } */ export function getRawFetchHeaders( headers: Headers ): RawHeadersMap | undefined { const headersList = getValueBySymbol('headers list', headers) if (!headersList) { return } const headersMap = getValueBySymbol< Map | Map >('headers map', headersList) /** * @note Older versions of Node.js (e.g. 18.8.0) keep headers map * as Map without any means to tap * into raw header values. Detect that and return undefined. */ if (!headersMap || !isHeadersMapWithRawHeaderNames(headersMap)) { return } // Raw headers is a map of { rawHeaderName: rawHeaderValue } const rawHeaders: RawHeadersMap = new Map() headersMap.forEach(({ name, value }) => { rawHeaders.set(name, value) }) return rawHeaders } function isHeadersMapWithRawHeaderNames( headersMap: Map | Map ): headersMap is Map { return Array.from( headersMap.values() as Iterable ).every((value) => { return isObject(value) && 'name' in value }) }