From 3986fb30c85275174d9397ec5098eb71a4af4c54 Mon Sep 17 00:00:00 2001 From: Pedro Cattori Date: Tue, 5 Dec 2023 17:58:46 -0500 Subject: [PATCH] Add support for HTTP2 pseudo headers (#55) * fix(headers): do not depend on `http` for header name validation Node internally uses undici instead anyway * fix(headers): support HTTP2 pseudo-headers which begin with `:` e.g. `:authority`, `:method`, etc. * test(headers): check that pseudo-headers are allowed --- .changeset/wise-dogs-clean.md | 5 +++++ packages/fetch/src/headers.js | 26 ++++++++++++-------------- packages/fetch/test/headers.js | 13 +++++++++++++ 3 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 .changeset/wise-dogs-clean.md diff --git a/.changeset/wise-dogs-clean.md b/.changeset/wise-dogs-clean.md new file mode 100644 index 0000000..b9fce00 --- /dev/null +++ b/.changeset/wise-dogs-clean.md @@ -0,0 +1,5 @@ +--- +"@remix-run/web-fetch": patch +--- + +Support HTTP2 pseudo-headers like `:authority`, `:method`, etc. diff --git a/packages/fetch/src/headers.js b/packages/fetch/src/headers.js index a5b566f..86ae2aa 100644 --- a/packages/fetch/src/headers.js +++ b/packages/fetch/src/headers.js @@ -8,21 +8,19 @@ import {types} from 'util'; import http from 'http'; import { isIterable } from './utils/is.js' -const validators = /** @type {{validateHeaderName?:(name:string) => any, validateHeaderValue?:(name:string, value:string) => any}} */ -(http) +/** @type {{validateHeaderValue?:(name:string, value:string) => any}} */ +const validators = (http) -const validateHeaderName = typeof validators.validateHeaderName === 'function' ? - validators.validateHeaderName : - /** - * @param {string} name - */ - name => { - if (!/^[\^`\-\w!#$%&'*+.|~]+$/.test(name)) { - const err = new TypeError(`Header name must be a valid HTTP token [${name}]`); - Object.defineProperty(err, 'code', {value: 'ERR_INVALID_HTTP_TOKEN'}); - throw err; - } - }; +/** + * @param {string} name + */ +const validateHeaderName = name => { + if (!/^[\^`\-\w!#$%&'*+.|~:]+$/.test(name)) { + const err = new TypeError(`Header name must be a valid HTTP token [${name}]`); + Object.defineProperty(err, 'code', {value: 'ERR_INVALID_HTTP_TOKEN'}); + throw err; + } +}; const validateHeaderValue = typeof validators.validateHeaderValue === 'function' ? validators.validateHeaderValue : diff --git a/packages/fetch/test/headers.js b/packages/fetch/test/headers.js index 94354cc..8f9e168 100644 --- a/packages/fetch/test/headers.js +++ b/packages/fetch/test/headers.js @@ -216,6 +216,19 @@ describe('Headers', () => { expect(() => headers.append('', 'ok')).to.throw(TypeError); }); + it('should allow HTTP2 pseudo-headers', () => { + let headers = new Headers({':authority': 'something'}); + headers.append(":method", "something else") + + const result = []; + for (const pair of headers) { + result.push(pair); + } + + expect(result).to.deep.equal([[':authority', 'something'], [':method', 'something else']]); + + }) + it('should ignore unsupported attributes while reading headers', () => { const FakeHeader = function () { }; // Prototypes are currently ignored