From 1766bb303d970c1c5b83e33f95e85df9a228b8c9 Mon Sep 17 00:00:00 2001 From: Konstantin Vyatkin Date: Wed, 27 May 2020 22:59:22 -0400 Subject: [PATCH 1/2] prefere native node function --- .github/workflows/ci.yml | 11 ++++---- src/headers.js | 60 ++++++++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1192f551..b9ddc412c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,12 +2,12 @@ name: CI on: push: - branches: [ master ] + branches: [master] pull_request: paths: - - '**.js' - - 'package.json' - - '.github/workflows/ci.yml' + - "**.js" + - "package.json" + - ".github/workflows/ci.yml" jobs: test: @@ -41,7 +41,6 @@ jobs: # upload coverage only once - name: Coveralls uses: coverallsapp/github-action@master - if: matrix.node == '14.x' && matrix.os == 'ubuntu-latest' + if: matrix.node == '12.x' && matrix.os == 'ubuntu-latest' with: github-token: ${{ secrets.GITHUB_TOKEN }} - diff --git a/src/headers.js b/src/headers.js index da1934fd8..cc10f5a75 100644 --- a/src/headers.js +++ b/src/headers.js @@ -5,23 +5,27 @@ */ import {types} from 'util'; +import http from 'http'; -const invalidTokenRegex = /[^`\-\w!#$%&'*+.|~]/; -const invalidHeaderCharRegex = /[^\t\u0020-\u007E\u0080-\u00FF]/; - -function validateName(name) { - name = String(name); - if (invalidTokenRegex.test(name) || name === '') { - throw new TypeError(`'${name}' is not a legal HTTP header name`); - } -} +const validateHeaderName = typeof http.validateHeaderName === 'function' ? + http.validateHeaderName : + name => { + if (/[^`\-\w!#$%&'*+.|~]/.test(name) || 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; + } + }; -function validateValue(value) { - value = String(value); - if (invalidHeaderCharRegex.test(value)) { - throw new TypeError(`'${value}' is not a legal HTTP header value`); - } -} +const validateHeaderValue = typeof http.validateHeaderValue === 'function' ? + http.validateHeaderValue : + (name, value) => { + if (/[^\t\u0020-\u007E\u0080-\u00FF]/.test(value)) { + const err = new TypeError(`Invalid character in header content ["${name}"]`); + Object.defineProperty(err, 'code', {value: 'ERR_INVALID_CHAR'}); + throw err; + } + }; /** * @typedef {Headers | Record | Iterable | Iterable[]} HeadersInit @@ -91,9 +95,9 @@ export default class Headers extends URLSearchParams { result = result.length > 0 ? result.map(([name, value]) => { - validateName(name); - validateValue(value); - return [String(name).toLowerCase(), value]; + validateHeaderName(name); + validateHeaderValue(name, String(value)); + return [String(name).toLowerCase(), String(value)]; }) : undefined; @@ -107,12 +111,12 @@ export default class Headers extends URLSearchParams { case 'append': case 'set': return (name, value) => { - validateName(name); - validateValue(value); + validateHeaderName(name); + validateHeaderValue(name, String(value)); return URLSearchParams.prototype[p].call( receiver, String(name).toLowerCase(), - value + String(value) ); }; @@ -120,7 +124,7 @@ export default class Headers extends URLSearchParams { case 'has': case 'getAll': return name => { - validateName(name); + validateHeaderName(name); return URLSearchParams.prototype[p].call( receiver, String(name).toLowerCase() @@ -142,7 +146,7 @@ export default class Headers extends URLSearchParams { } get [Symbol.toStringTag]() { - return 'Headers'; + return this.constructor.name; } toString() { @@ -247,7 +251,15 @@ export function fromRawHeaders(headers = []) { return result; }, []) - .filter(([name, value]) => !(invalidTokenRegex.test(name) || invalidHeaderCharRegex.test(value))) + .filter(([name, value]) => { + try { + validateHeaderName(name); + validateHeaderValue(name, String(value)); + return true; + } catch { + return false; + } + }) ); } From fe0979b8e85b4cf3b34b777355091f270caec9fc Mon Sep 17 00:00:00 2001 From: Konstantin Vyatkin Date: Sat, 30 May 2020 20:37:38 -0400 Subject: [PATCH 2/2] use RegExp from Node 14.3 --- src/headers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/headers.js b/src/headers.js index cc10f5a75..5091152ec 100644 --- a/src/headers.js +++ b/src/headers.js @@ -10,7 +10,7 @@ import http from 'http'; const validateHeaderName = typeof http.validateHeaderName === 'function' ? http.validateHeaderName : name => { - if (/[^`\-\w!#$%&'*+.|~]/.test(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;