From 942efdbe4723659a1299833334ccb5abf3e3a118 Mon Sep 17 00:00:00 2001 From: Daniel Hensby Date: Sat, 17 Sep 2022 10:02:24 +0100 Subject: [PATCH 1/2] Add header extraction test based on spec --- src/httpbis/index.ts | 9 ++++----- test/httpbis/httpbis.ts | 36 +++++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/httpbis/index.ts b/src/httpbis/index.ts index 1830ea5..8aaa2f2 100644 --- a/src/httpbis/index.ts +++ b/src/httpbis/index.ts @@ -25,11 +25,10 @@ export function extractHeader({ headers }: RequestLike | ResponseLike, header: s if (!allowMissing && !key) { throw new Error(`Unable to extract header "${header}" from message`); } - let val = key ? headers[key] ?? '' : ''; - if (Array.isArray(val)) { - val = val.join(', '); - } - return val.toString().replace(/\s+/g, ' '); + const val = key ? headers[key] ?? '' : ''; + return (!Array.isArray(val) ? [val] : val).map((v) => { + return v.toString().trim().replace(/\n+\s*/g, ' '); + }).join(', '); } function populateDefaultParameters(parameters: Parameters) { diff --git a/test/httpbis/httpbis.ts b/test/httpbis/httpbis.ts index 3dd5fc4..ed2c1aa 100644 --- a/test/httpbis/httpbis.ts +++ b/test/httpbis/httpbis.ts @@ -5,22 +5,28 @@ import { expect } from 'chai'; describe('httpbis', () => { describe('.extractHeader', () => { const headers = { - 'testheader': 'test', - 'test-header-1': 'test1', - 'Test-Header-2': 'test2', - 'test-Header-3': 'test3', - 'TEST-HEADER-4': 'test4', + 'Host': 'www.example.com', + 'Date': 'Tue, 20 Apr 2021 02:07:56 GMT', + 'X-OWS-Header': ' Leading and trailing whitespace. ', + 'X-Obs-Fold-Header': 'Obsolete\nline folding.', + 'Cache-Control': ['max-age=60', ' must-revalidate'], + 'Example-Dict': ' a=1, b=2;x=1;y=2, c=(a b c)', }; - Object.entries(headers).forEach(([headerName, expectedValue]) => { - it(`successfully extracts a matching header (${headerName})`, () => { - expect(extractHeader({ headers } as unknown as RequestLike, headerName)).to.equal(expectedValue); - }); - it(`successfully extracts a lower cased header (${headerName})`, () => { - expect(extractHeader({ headers } as unknown as RequestLike, headerName.toLowerCase())).to.equal(expectedValue); - }); - it(`successfully extracts an upper cased header (${headerName})`, () => { - expect(extractHeader({ headers } as unknown as RequestLike, headerName.toUpperCase())).to.equal(expectedValue); - }); + it('correctly extracts headers', () => { + const expected = { + 'host': 'www.example.com', + 'date': 'Tue, 20 Apr 2021 02:07:56 GMT', + 'x-ows-header': 'Leading and trailing whitespace.', + 'x-obs-fold-header': 'Obsolete line folding.', + 'cache-control': 'max-age=60, must-revalidate', + 'example-dict': 'a=1, b=2;x=1;y=2, c=(a b c)', + }; + const parsed = Object.keys(headers).reduce((accum, name) => { + return Object.assign(accum, { + [name.toLowerCase()]: extractHeader({ headers } as unknown as RequestLike, name), + }); + }, {}); + expect(parsed).to.deep.equal(expected); }); it('allows missing headers to return by default', () => { expect(extractHeader({ headers } as unknown as RequestLike, 'missing')).to.equal(''); From 14aa867a782e8b9e2b302750123efc1e5ccc6ce0 Mon Sep 17 00:00:00 2001 From: Daniel Hensby Date: Sat, 17 Sep 2022 10:10:46 +0100 Subject: [PATCH 2/2] Empty/missing headers should be extracted as single spacce --- src/httpbis/index.ts | 2 +- test/httpbis/httpbis.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/httpbis/index.ts b/src/httpbis/index.ts index 8aaa2f2..fd180cc 100644 --- a/src/httpbis/index.ts +++ b/src/httpbis/index.ts @@ -27,7 +27,7 @@ export function extractHeader({ headers }: RequestLike | ResponseLike, header: s } const val = key ? headers[key] ?? '' : ''; return (!Array.isArray(val) ? [val] : val).map((v) => { - return v.toString().trim().replace(/\n+\s*/g, ' '); + return v.toString().trim().replace(/\n+\s*/g, ' ') || ' '; }).join(', '); } diff --git a/test/httpbis/httpbis.ts b/test/httpbis/httpbis.ts index ed2c1aa..7322b37 100644 --- a/test/httpbis/httpbis.ts +++ b/test/httpbis/httpbis.ts @@ -28,14 +28,18 @@ describe('httpbis', () => { }, {}); expect(parsed).to.deep.equal(expected); }); + it('extracts an empty header', () => { + const parsed = extractHeader({ headers: { 'x-empty-header': '' } } as unknown as RequestLike, 'x-empty-header'); + expect(parsed).to.equal(' '); + }); it('allows missing headers to return by default', () => { - expect(extractHeader({ headers } as unknown as RequestLike, 'missing')).to.equal(''); + expect(extractHeader({ headers } as unknown as RequestLike, 'missing')).to.equal(' '); }); it('throws on missing headers', () => { expect(() => extractHeader({ headers } as unknown as RequestLike, 'missing', { allowMissing: false })).to.throw(Error, 'Unable to extract header "missing" from message'); }); it('does not throw on missing headers', () => { - expect(extractHeader({ headers } as unknown as RequestLike, 'missing', { allowMissing: true })).to.equal(''); + expect(extractHeader({ headers } as unknown as RequestLike, 'missing', { allowMissing: true })).to.equal(' '); }); }); describe('.extractComponent', () => {