summaryrefslogtreecommitdiff
path: root/extensions/fetch/20_headers.js
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2021-08-11 12:27:05 +0200
committerGitHub <noreply@github.com>2021-08-11 12:27:05 +0200
commita0285e2eb88f6254f6494b0ecd1878db3a3b2a58 (patch)
tree90671b004537e20f9493fd3277ffd21d30b39a0e /extensions/fetch/20_headers.js
parent3a6994115176781b3a93d70794b1b81bc95e42b4 (diff)
Rename extensions/ directory to ext/ (#11643)
Diffstat (limited to 'extensions/fetch/20_headers.js')
-rw-r--r--extensions/fetch/20_headers.js479
1 files changed, 0 insertions, 479 deletions
diff --git a/extensions/fetch/20_headers.js b/extensions/fetch/20_headers.js
deleted file mode 100644
index 91154d958..000000000
--- a/extensions/fetch/20_headers.js
+++ /dev/null
@@ -1,479 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// @ts-check
-/// <reference path="../webidl/internal.d.ts" />
-/// <reference path="../web/internal.d.ts" />
-/// <reference path="../web/lib.deno_web.d.ts" />
-/// <reference path="./internal.d.ts" />
-/// <reference path="../web/06_streams_types.d.ts" />
-/// <reference path="./lib.deno_fetch.d.ts" />
-/// <reference lib="esnext" />
-"use strict";
-
-((window) => {
- const webidl = window.__bootstrap.webidl;
- const {
- HTTP_TAB_OR_SPACE_PREFIX_RE,
- HTTP_TAB_OR_SPACE_SUFFIX_RE,
- HTTP_WHITESPACE_PREFIX_RE,
- HTTP_WHITESPACE_SUFFIX_RE,
- HTTP_TOKEN_CODE_POINT_RE,
- byteLowerCase,
- collectSequenceOfCodepoints,
- collectHttpQuotedString,
- } = window.__bootstrap.infra;
- const {
- ArrayIsArray,
- ArrayPrototypeMap,
- ArrayPrototypePush,
- ArrayPrototypeSort,
- ArrayPrototypeJoin,
- ArrayPrototypeSplice,
- ArrayPrototypeFilter,
- ObjectKeys,
- ObjectEntries,
- RegExpPrototypeTest,
- Symbol,
- SymbolFor,
- SymbolIterator,
- SymbolToStringTag,
- StringPrototypeReplaceAll,
- StringPrototypeIncludes,
- TypeError,
- } = window.__bootstrap.primordials;
-
- const _headerList = Symbol("header list");
- const _iterableHeaders = Symbol("iterable headers");
- const _guard = Symbol("guard");
-
- /**
- * @typedef Header
- * @type {[string, string]}
- */
-
- /**
- * @typedef HeaderList
- * @type {Header[]}
- */
-
- /**
- * @param {string} potentialValue
- * @returns {string}
- */
- function normalizeHeaderValue(potentialValue) {
- potentialValue = StringPrototypeReplaceAll(
- potentialValue,
- HTTP_WHITESPACE_PREFIX_RE,
- "",
- );
- potentialValue = StringPrototypeReplaceAll(
- potentialValue,
- HTTP_WHITESPACE_SUFFIX_RE,
- "",
- );
- return potentialValue;
- }
-
- /**
- * @param {Headers} headers
- * @param {HeadersInit} object
- */
- function fillHeaders(headers, object) {
- if (ArrayIsArray(object)) {
- for (const header of object) {
- if (header.length !== 2) {
- throw new TypeError(
- `Invalid header. Length must be 2, but is ${header.length}`,
- );
- }
- appendHeader(headers, header[0], header[1]);
- }
- } else {
- for (const key of ObjectKeys(object)) {
- appendHeader(headers, key, object[key]);
- }
- }
- }
-
- /**
- * https://fetch.spec.whatwg.org/#concept-headers-append
- * @param {Headers} headers
- * @param {string} name
- * @param {string} value
- */
- function appendHeader(headers, name, value) {
- // 1.
- value = normalizeHeaderValue(value);
-
- // 2.
- if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) {
- throw new TypeError("Header name is not valid.");
- }
- if (
- StringPrototypeIncludes(value, "\x00") ||
- StringPrototypeIncludes(value, "\x0A") ||
- StringPrototypeIncludes(value, "\x0D")
- ) {
- throw new TypeError("Header value is not valid.");
- }
-
- // 3.
- if (headers[_guard] == "immutable") {
- throw new TypeError("Headers are immutable.");
- }
-
- // 7.
- const list = headers[_headerList];
- name = byteLowerCase(name);
- ArrayPrototypePush(list, [name, value]);
- }
-
- /**
- * https://fetch.spec.whatwg.org/#concept-header-list-get
- * @param {HeaderList} list
- * @param {string} name
- */
- function getHeader(list, name) {
- const lowercaseName = byteLowerCase(name);
- const entries = ArrayPrototypeMap(
- ArrayPrototypeFilter(list, (entry) => entry[0] === lowercaseName),
- (entry) => entry[1],
- );
- if (entries.length === 0) {
- return null;
- } else {
- return ArrayPrototypeJoin(entries, "\x2C\x20");
- }
- }
-
- /**
- * https://fetch.spec.whatwg.org/#concept-header-list-get-decode-split
- * @param {HeaderList} list
- * @param {string} name
- * @returns {string[] | null}
- */
- function getDecodeSplitHeader(list, name) {
- const initialValue = getHeader(list, name);
- if (initialValue === null) return null;
- const input = initialValue;
- let position = 0;
- const values = [];
- let value = "";
- while (position < initialValue.length) {
- // 7.1. collect up to " or ,
- const res = collectSequenceOfCodepoints(
- initialValue,
- position,
- (c) => c !== "\u0022" && c !== "\u002C",
- );
- value += res.result;
- position = res.position;
-
- if (position < initialValue.length) {
- if (input[position] === "\u0022") {
- const res = collectHttpQuotedString(input, position, false);
- value += res.result;
- position = res.position;
- if (position < initialValue.length) {
- continue;
- }
- } else {
- if (input[position] !== "\u002C") throw new TypeError("Unreachable");
- position += 1;
- }
- }
-
- value = StringPrototypeReplaceAll(value, HTTP_TAB_OR_SPACE_PREFIX_RE, "");
- value = StringPrototypeReplaceAll(value, HTTP_TAB_OR_SPACE_SUFFIX_RE, "");
-
- ArrayPrototypePush(values, value);
- value = "";
- }
- return values;
- }
-
- class Headers {
- /** @type {HeaderList} */
- [_headerList] = [];
- /** @type {"immutable" | "request" | "request-no-cors" | "response" | "none"} */
- [_guard];
-
- get [_iterableHeaders]() {
- const list = this[_headerList];
-
- // The order of steps are not similar to the ones suggested by the
- // spec but produce the same result.
- const headers = {};
- const cookies = [];
- for (const entry of list) {
- const name = entry[0];
- const value = entry[1];
- if (value === null) throw new TypeError("Unreachable");
- // The following if statement is not spec compliant.
- // `set-cookie` is the only header that can not be concatentated,
- // so must be given to the user as multiple headers.
- // The else block of the if statement is spec compliant again.
- if (name === "set-cookie") {
- ArrayPrototypePush(cookies, [name, value]);
- } else {
- // The following code has the same behaviour as getHeader()
- // at the end of loop. But it avoids looping through the entire
- // list to combine multiple values with same header name. It
- // instead gradually combines them as they are found.
- let header = headers[name];
- if (header && header.length > 0) {
- header += "\x2C\x20" + value;
- } else {
- header = value;
- }
- headers[name] = header;
- }
- }
-
- return ArrayPrototypeSort(
- [...ObjectEntries(headers), ...cookies],
- (a, b) => {
- const akey = a[0];
- const bkey = b[0];
- if (akey > bkey) return 1;
- if (akey < bkey) return -1;
- return 0;
- },
- );
- }
-
- /** @param {HeadersInit} [init] */
- constructor(init = undefined) {
- const prefix = "Failed to construct 'Event'";
- if (init !== undefined) {
- init = webidl.converters["HeadersInit"](init, {
- prefix,
- context: "Argument 1",
- });
- }
-
- this[webidl.brand] = webidl.brand;
- this[_guard] = "none";
- if (init !== undefined) {
- fillHeaders(this, init);
- }
- }
-
- /**
- * @param {string} name
- * @param {string} value
- */
- append(name, value) {
- webidl.assertBranded(this, Headers);
- const prefix = "Failed to execute 'append' on 'Headers'";
- webidl.requiredArguments(arguments.length, 2, { prefix });
- name = webidl.converters["ByteString"](name, {
- prefix,
- context: "Argument 1",
- });
- value = webidl.converters["ByteString"](value, {
- prefix,
- context: "Argument 2",
- });
- appendHeader(this, name, value);
- }
-
- /**
- * @param {string} name
- */
- delete(name) {
- const prefix = "Failed to execute 'delete' on 'Headers'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- name = webidl.converters["ByteString"](name, {
- prefix,
- context: "Argument 1",
- });
-
- if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) {
- throw new TypeError("Header name is not valid.");
- }
- if (this[_guard] == "immutable") {
- throw new TypeError("Headers are immutable.");
- }
-
- const list = this[_headerList];
- name = byteLowerCase(name);
- for (let i = 0; i < list.length; i++) {
- if (list[i][0] === name) {
- ArrayPrototypeSplice(list, i, 1);
- i--;
- }
- }
- }
-
- /**
- * @param {string} name
- */
- get(name) {
- const prefix = "Failed to execute 'get' on 'Headers'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- name = webidl.converters["ByteString"](name, {
- prefix,
- context: "Argument 1",
- });
-
- if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) {
- throw new TypeError("Header name is not valid.");
- }
-
- const list = this[_headerList];
- return getHeader(list, name);
- }
-
- /**
- * @param {string} name
- */
- has(name) {
- const prefix = "Failed to execute 'has' on 'Headers'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- name = webidl.converters["ByteString"](name, {
- prefix,
- context: "Argument 1",
- });
-
- if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) {
- throw new TypeError("Header name is not valid.");
- }
-
- const list = this[_headerList];
- name = byteLowerCase(name);
- for (let i = 0; i < list.length; i++) {
- if (list[i][0] === name) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * @param {string} name
- * @param {string} value
- */
- set(name, value) {
- webidl.assertBranded(this, Headers);
- const prefix = "Failed to execute 'set' on 'Headers'";
- webidl.requiredArguments(arguments.length, 2, { prefix });
- name = webidl.converters["ByteString"](name, {
- prefix,
- context: "Argument 1",
- });
- value = webidl.converters["ByteString"](value, {
- prefix,
- context: "Argument 2",
- });
-
- value = normalizeHeaderValue(value);
-
- // 2.
- if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) {
- throw new TypeError("Header name is not valid.");
- }
- if (
- StringPrototypeIncludes(value, "\x00") ||
- StringPrototypeIncludes(value, "\x0A") ||
- StringPrototypeIncludes(value, "\x0D")
- ) {
- throw new TypeError("Header value is not valid.");
- }
-
- if (this[_guard] == "immutable") {
- throw new TypeError("Headers are immutable.");
- }
-
- const list = this[_headerList];
- name = byteLowerCase(name);
- let added = false;
- for (let i = 0; i < list.length; i++) {
- if (list[i][0] === name) {
- if (!added) {
- list[i][1] = value;
- added = true;
- } else {
- ArrayPrototypeSplice(list, i, 1);
- i--;
- }
- }
- }
- if (!added) {
- ArrayPrototypePush(list, [name, value]);
- }
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- const headers = {};
- for (const header of this) {
- headers[header[0]] = header[1];
- }
- return `Headers ${inspect(headers)}`;
- }
-
- get [SymbolToStringTag]() {
- return "Headers";
- }
- }
-
- webidl.mixinPairIterable("Headers", Headers, _iterableHeaders, 0, 1);
-
- webidl.configurePrototype(Headers);
-
- webidl.converters["HeadersInit"] = (V, opts) => {
- // Union for (sequence<sequence<ByteString>> or record<ByteString, ByteString>)
- if (webidl.type(V) === "Object" && V !== null) {
- if (V[SymbolIterator] !== undefined) {
- return webidl.converters["sequence<sequence<ByteString>>"](V, opts);
- }
- return webidl.converters["record<ByteString, ByteString>"](V, opts);
- }
- throw webidl.makeException(
- TypeError,
- "The provided value is not of type '(sequence<sequence<ByteString>> or record<ByteString, ByteString>)'",
- opts,
- );
- };
- webidl.converters["Headers"] = webidl.createInterfaceConverter(
- "Headers",
- Headers,
- );
-
- /**
- * @param {HeaderList} list
- * @param {"immutable" | "request" | "request-no-cors" | "response" | "none"} guard
- * @returns {Headers}
- */
- function headersFromHeaderList(list, guard) {
- const headers = webidl.createBranded(Headers);
- headers[_headerList] = list;
- headers[_guard] = guard;
- return headers;
- }
-
- /**
- * @param {Headers}
- * @returns {HeaderList}
- */
- function headerListFromHeaders(headers) {
- return headers[_headerList];
- }
-
- /**
- * @param {Headers}
- * @returns {"immutable" | "request" | "request-no-cors" | "response" | "none"}
- */
- function guardFromHeaders(headers) {
- return headers[_guard];
- }
-
- window.__bootstrap.headers = {
- Headers,
- headersFromHeaderList,
- headerListFromHeaders,
- fillHeaders,
- getDecodeSplitHeader,
- guardFromHeaders,
- };
-})(this);