From aa9cb1854892dbe453eb8135b54489fe0c7cd009 Mon Sep 17 00:00:00 2001 From: JaoodxD Date: Tue, 6 Feb 2024 16:43:00 +0200 Subject: [PATCH 1/7] Update tests with iterable object cases --- test/request.js | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/test/request.js b/test/request.js index 30bf745c3f1..0f5c826ab8c 100644 --- a/test/request.js +++ b/test/request.js @@ -246,3 +246,103 @@ test('DispatchOptions#reset', scope => { }) }) }) + +test('Should include headers from iterable objects', scope => { + scope.plan(3) + + scope.test('Should include headers built with Headers global object', async t => { + const server = createServer((req, res) => { + t.equal('GET', req.method) + t.equal(`localhost:${server.address().port}`, req.headers.host) + t.equal(req.headers.hello, 'world') + res.statusCode = 200 + res.end('hello') + }) + + const headers = new Headers() + headers.set('hello', 'world') + + t.plan(3) + + t.teardown(server.close.bind(server)) + + await new Promise((resolve, reject) => { + server.listen(0, (err) => { + if (err != null) reject(err) + else resolve() + }) + }) + + await request({ + method: 'GET', + origin: `http://localhost:${server.address().port}`, + reset: true, + headers + }) + }) + + scope.test('Should include headers built with Map', async t => { + const server = createServer((req, res) => { + t.equal('GET', req.method) + t.equal(`localhost:${server.address().port}`, req.headers.host) + t.equal(req.headers.hello, 'world') + res.statusCode = 200 + res.end('hello') + }) + + const headers = new Map() + headers.set('hello', 'world') + + t.plan(3) + + t.teardown(server.close.bind(server)) + + await new Promise((resolve, reject) => { + server.listen(0, (err) => { + if (err != null) reject(err) + else resolve() + }) + }) + + await request({ + method: 'GET', + origin: `http://localhost:${server.address().port}`, + reset: true, + headers + }) + }) + + scope.test('Should include headers built with custom iterable object', async t => { + const server = createServer((req, res) => { + t.equal('GET', req.method) + t.equal(`localhost:${server.address().port}`, req.headers.host) + t.equal(req.headers.hello, 'world') + res.statusCode = 200 + res.end('hello') + }) + + const headers = { + * [Symbol.iterator] () { + yield ['hello', 'world'] + } + } + + t.plan(3) + + t.teardown(server.close.bind(server)) + + await new Promise((resolve, reject) => { + server.listen(0, (err) => { + if (err != null) reject(err) + else resolve() + }) + }) + + await request({ + method: 'GET', + origin: `http://localhost:${server.address().port}`, + reset: true, + headers + }) + }) +}) From 703bbc87332626bb2400d67713ad5364c6bbb1c2 Mon Sep 17 00:00:00 2001 From: JaoodxD Date: Tue, 6 Feb 2024 16:44:39 +0200 Subject: [PATCH 2/7] Add support for iterable object headers --- lib/core/request.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/core/request.js b/lib/core/request.js index 74e0ca16eaa..fc8705e9268 100644 --- a/lib/core/request.js +++ b/lib/core/request.js @@ -164,10 +164,18 @@ class Request { processHeader(this, headers[i], headers[i + 1]) } } else if (headers && typeof headers === 'object') { - const keys = Object.keys(headers) - for (let i = 0; i < keys.length; i++) { - const key = keys[i] - processHeader(this, key, headers[key]) + if (headers[Symbol.iterator]) { + for (const header of headers) { + const key = header[0] + const value = header[1] + processHeader(this, key, value) + } + } else { + const keys = Object.keys(headers) + for (let i = 0; i < keys.length; i++) { + const key = keys[i] + processHeader(this, key, headers[key]) + } } } else if (headers != null) { throw new InvalidArgumentError('headers must be an object or an array') From fcc4cc91faf2c5cf9cad6c5a9bc0b0257d687402 Mon Sep 17 00:00:00 2001 From: JaoodxD Date: Tue, 6 Feb 2024 19:41:52 +0200 Subject: [PATCH 3/7] Update tests with cases of malformed headers --- test/request.js | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/test/request.js b/test/request.js index 0f5c826ab8c..bbfab5b3f5c 100644 --- a/test/request.js +++ b/test/request.js @@ -2,7 +2,7 @@ const { createServer } = require('node:http') const { test } = require('tap') -const { request } = require('..') +const { request, errors } = require('..') test('no-slash/one-slash pathname should be included in req.path', async (t) => { const pathServer = createServer((req, res) => { @@ -248,7 +248,7 @@ test('DispatchOptions#reset', scope => { }) test('Should include headers from iterable objects', scope => { - scope.plan(3) + scope.plan(4) scope.test('Should include headers built with Headers global object', async t => { const server = createServer((req, res) => { @@ -345,4 +345,37 @@ test('Should include headers from iterable objects', scope => { headers }) }) + + scope.test('Should throw error if headers iterable object does not yield key-value pairs', async t => { + const server = createServer((req, res) => { + res.end('hello') + }) + + const headers = { + * [Symbol.iterator] () { + yield 'Bad formatted header' + } + } + + t.plan(2) + + t.teardown(server.close.bind(server)) + + await new Promise((resolve, reject) => { + server.listen(0, (err) => { + if (err != null) reject(err) + else resolve() + }) + }) + + await request({ + method: 'GET', + origin: `http://localhost:${server.address().port}`, + reset: true, + headers + }).catch((err) => { + t.type(err, errors.InvalidArgumentError) + t.equal(err.message, 'headers must be in key-value pair format') + }) + }) }) From a6913dd230ba989d2e7c36ed0b8b5c919af5f2d6 Mon Sep 17 00:00:00 2001 From: JaoodxD Date: Tue, 6 Feb 2024 19:45:08 +0200 Subject: [PATCH 4/7] Add check for malformed headers --- lib/core/request.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/core/request.js b/lib/core/request.js index fc8705e9268..3711a49301a 100644 --- a/lib/core/request.js +++ b/lib/core/request.js @@ -166,6 +166,9 @@ class Request { } else if (headers && typeof headers === 'object') { if (headers[Symbol.iterator]) { for (const header of headers) { + if (!Array.isArray(header) || header.length !== 2) { + throw new InvalidArgumentError('headers must be in key-value pair format') + } const key = header[0] const value = header[1] processHeader(this, key, value) From eb438dc46639ee17cb911ba51a0c6fe466912afc Mon Sep 17 00:00:00 2001 From: Maksym Shenderuk Date: Wed, 7 Feb 2024 13:41:36 +0300 Subject: [PATCH 5/7] Update lib/core/request.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mert Can Altın --- lib/core/request.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/core/request.js b/lib/core/request.js index 3711a49301a..d4f50b2db88 100644 --- a/lib/core/request.js +++ b/lib/core/request.js @@ -169,8 +169,7 @@ class Request { if (!Array.isArray(header) || header.length !== 2) { throw new InvalidArgumentError('headers must be in key-value pair format') } - const key = header[0] - const value = header[1] + const [key, value] = header; processHeader(this, key, value) } } else { From 1531e5f70edb255c5a61ccfcbb4f1ce7864c8fb6 Mon Sep 17 00:00:00 2001 From: Maksym Shenderuk Date: Wed, 7 Feb 2024 15:34:57 +0300 Subject: [PATCH 6/7] Update lib/core/request.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mert Can Altın --- lib/core/request.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core/request.js b/lib/core/request.js index d4f50b2db88..2647656b40b 100644 --- a/lib/core/request.js +++ b/lib/core/request.js @@ -174,7 +174,7 @@ class Request { } } else { const keys = Object.keys(headers) - for (let i = 0; i < keys.length; i++) { + for (const key of keys) { const key = keys[i] processHeader(this, key, headers[key]) } From ff17709ad64c64bc948034f6408155c4aae0ece9 Mon Sep 17 00:00:00 2001 From: JaoodxD Date: Fri, 9 Feb 2024 17:32:15 +0200 Subject: [PATCH 7/7] Fix code after unverified improvement broke functionality --- lib/core/request.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/core/request.js b/lib/core/request.js index 2647656b40b..bee7a47af92 100644 --- a/lib/core/request.js +++ b/lib/core/request.js @@ -169,13 +169,12 @@ class Request { if (!Array.isArray(header) || header.length !== 2) { throw new InvalidArgumentError('headers must be in key-value pair format') } - const [key, value] = header; + const [key, value] = header processHeader(this, key, value) } } else { const keys = Object.keys(headers) for (const key of keys) { - const key = keys[i] processHeader(this, key, headers[key]) } }