summaryrefslogtreecommitdiff
path: root/js/headers.ts
diff options
context:
space:
mode:
authorKevin (Kun) "Kassimo" Qian <kevinkassimo@gmail.com>2018-12-19 02:57:23 -0500
committerRyan Dahl <ry@tinyclouds.org>2018-12-19 02:57:23 -0500
commit57338d98bef93bb45c8aff945ccec5d310d3c241 (patch)
tree15275505d71e151d472ba156304666f54f61416b /js/headers.ts
parent22874d44a65ed670735fb0d7f6bc8de45f13620a (diff)
Add illegal header name and value guards (#1375)
Diffstat (limited to 'js/headers.ts')
-rw-r--r--js/headers.ts33
1 files changed, 33 insertions, 0 deletions
diff --git a/js/headers.ts b/js/headers.ts
index 1b47ac7d3..ca99d5789 100644
--- a/js/headers.ts
+++ b/js/headers.ts
@@ -2,6 +2,11 @@
import * as domTypes from "./dom_types";
import { DomIterableMixin } from "./mixins/dom_iterable";
+// From node-fetch
+// Copyright (c) 2016 David Frank. MIT License.
+const invalidTokenRegex = /[^\^_`a-zA-Z\-0-9!#$%&'*+.|~]/;
+const invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
+
// tslint:disable-next-line:no-any
function isHeaders(value: any): value is domTypes.Headers {
return value instanceof Headers;
@@ -12,6 +17,8 @@ const headerMap = Symbol("header map");
// ref: https://fetch.spec.whatwg.org/#dom-headers
class HeadersBase {
private [headerMap]: Map<string, string>;
+ // TODO: headerGuard? Investigate if it is needed
+ // node-fetch did not implement this but it is in the spec
private _normalizeParams(name: string, value?: string): string[] {
name = String(name).toLowerCase();
@@ -19,6 +26,20 @@ class HeadersBase {
return [name, value];
}
+ // The following name/value validations are copied from
+ // https://github.com/bitinn/node-fetch/blob/master/src/headers.js
+ // Copyright (c) 2016 David Frank. MIT License.
+ private _validateName(name: string) {
+ if (invalidTokenRegex.test(name)) {
+ throw new TypeError(`${name} is not a legal HTTP header name`);
+ }
+ }
+ private _validateValue(value: string) {
+ if (invalidHeaderCharRegex.test(value)) {
+ throw new TypeError(`${value} is not a legal HTTP header value`);
+ }
+ }
+
constructor(init?: domTypes.HeadersInit) {
if (init === null) {
throw new TypeError(
@@ -31,6 +52,8 @@ class HeadersBase {
if (Array.isArray(init)) {
for (const [rawName, rawValue] of init) {
const [name, value] = this._normalizeParams(rawName, rawValue);
+ this._validateName(name);
+ this._validateValue(value);
const existingValue = this[headerMap].get(name);
this[headerMap].set(
name,
@@ -42,14 +65,19 @@ class HeadersBase {
for (const rawName of names) {
const rawValue = init[rawName];
const [name, value] = this._normalizeParams(rawName, rawValue);
+ this._validateName(name);
+ this._validateValue(value);
this[headerMap].set(name, value);
}
}
}
}
+ // ref: https://fetch.spec.whatwg.org/#concept-headers-append
append(name: string, value: string): void {
const [newname, newvalue] = this._normalizeParams(name, value);
+ this._validateName(newname);
+ this._validateValue(newvalue);
const v = this[headerMap].get(newname);
const str = v ? `${v}, ${newvalue}` : newvalue;
this[headerMap].set(newname, str);
@@ -57,22 +85,27 @@ class HeadersBase {
delete(name: string): void {
const [newname] = this._normalizeParams(name);
+ this._validateName(newname);
this[headerMap].delete(newname);
}
get(name: string): string | null {
const [newname] = this._normalizeParams(name);
+ this._validateName(newname);
const value = this[headerMap].get(newname);
return value || null;
}
has(name: string): boolean {
const [newname] = this._normalizeParams(name);
+ this._validateName(newname);
return this[headerMap].has(newname);
}
set(name: string, value: string): void {
const [newname, newvalue] = this._normalizeParams(name, value);
+ this._validateName(newname);
+ this._validateValue(newvalue);
this[headerMap].set(newname, newvalue);
}
}