cloudflare/cloudflare-typescript

Public

mirrored from https://github.com/cloudflare/cloudflare-typescriptAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
0f711a6ec6dfa3a06bb7b4f9dcb2223ac65707d9

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/internal/headers.ts

97lines · modecode

1// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
3import { isReadonlyArray } from './utils/values';
4
5type HeaderValue = string | undefined | null;
6export type HeadersLike =
7 | Headers
8 | readonly HeaderValue[][]
9 | Record<string, HeaderValue | readonly HeaderValue[]>
10 | undefined
11 | null
12 | NullableHeaders;
13
14const brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders');
15
16/**
17 * @internal
18 * Users can pass explicit nulls to unset default headers. When we parse them
19 * into a standard headers type we need to preserve that information.
20 */
21export type NullableHeaders = {
22 /** Brand check, prevent users from creating a NullableHeaders. */
23 [brand_privateNullableHeaders]: true;
24 /** Parsed headers. */
25 values: Headers;
26 /** Set of lowercase header names explicitly set to null. */
27 nulls: Set<string>;
28};
29
30function* iterateHeaders(headers: HeadersLike): IterableIterator<readonly [string, string | null]> {
31 if (!headers) return;
32
33 if (brand_privateNullableHeaders in headers) {
34 const { values, nulls } = headers;
35 yield* values.entries();
36 for (const name of nulls) {
37 yield [name, null];
38 }
39 return;
40 }
41
42 let shouldClear = false;
43 let iter: Iterable<readonly (HeaderValue | readonly HeaderValue[])[]>;
44 if (headers instanceof Headers) {
45 iter = headers.entries();
46 } else if (isReadonlyArray(headers)) {
47 iter = headers;
48 } else {
49 shouldClear = true;
50 iter = Object.entries(headers ?? {});
51 }
52 for (let row of iter) {
53 const name = row[0];
54 if (typeof name !== 'string') throw new TypeError('expected header name to be a string');
55 const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];
56 let didClear = false;
57 for (const value of values) {
58 if (value === undefined) continue;
59
60 // Objects keys always overwrite older headers, they never append.
61 // Yield a null to clear the header before adding the new values.
62 if (shouldClear && !didClear) {
63 didClear = true;
64 yield [name, null];
65 }
66 yield [name, value];
67 }
68 }
69}
70
71export const buildHeaders = (newHeaders: HeadersLike[]): NullableHeaders => {
72 const targetHeaders = new Headers();
73 const nullHeaders = new Set<string>();
74 for (const headers of newHeaders) {
75 const seenHeaders = new Set<string>();
76 for (const [name, value] of iterateHeaders(headers)) {
77 const lowerName = name.toLowerCase();
78 if (!seenHeaders.has(lowerName)) {
79 targetHeaders.delete(name);
80 seenHeaders.add(lowerName);
81 }
82 if (value === null) {
83 targetHeaders.delete(name);
84 nullHeaders.add(lowerName);
85 } else {
86 targetHeaders.append(name, value);
87 nullHeaders.delete(lowerName);
88 }
89 }
90 }
91 return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };
92};
93
94export const isEmptyHeaders = (headers: HeadersLike) => {
95 for (const _ of iterateHeaders(headers)) return false;
96 return true;
97};
98