From 1e43edcf7bca63c1a3291b714960ede36ad8c0aa Mon Sep 17 00:00:00 2001 From: will Farrell Date: Tue, 7 Nov 2023 19:51:21 -0700 Subject: [PATCH] feat: add in option to set default headers --- .../http-header-normalizer/__tests__/index.js | 82 +++++++++++++++++++ packages/http-header-normalizer/index.d.ts | 5 +- packages/http-header-normalizer/index.js | 11 ++- .../docs/middlewares/http-event-normalizer.md | 19 ----- .../middlewares/http-header-normalizer.md | 16 ++-- 5 files changed, 101 insertions(+), 32 deletions(-) diff --git a/packages/http-header-normalizer/__tests__/index.js b/packages/http-header-normalizer/__tests__/index.js index 51be68811..c60f40c74 100644 --- a/packages/http-header-normalizer/__tests__/index.js +++ b/packages/http-header-normalizer/__tests__/index.js @@ -107,6 +107,47 @@ test('It can use custom normalization function', async (t) => { t.deepEqual(resultingEvent.rawHeaders, originalHeaders) }) +test('It should normalize (lowercase) all the headers with defaults', async (t) => { + const handler = middy() + .use( + httpHeaderNormalizer({ + defaultHeaders: { + 'Content-Type': 'application/json', + Accept: '*/*' + } + }) + ) + .handler((event, context) => event) + + const event = { + headers: { + 'x-aPi-key': '123456', + tcn: 'abc', + te: 'cde', + DNS: 'd', + FOO: 'bar', + Accept: 'application/json' + } + } + + const expectedHeaders = { + 'x-api-key': '123456', + tcn: 'abc', + te: 'cde', + dns: 'd', + foo: 'bar', + accept: 'application/json', + 'content-type': 'application/json' + } + + const originalHeaders = { ...event.headers } + + const resultingEvent = await handler(event, context) + + t.deepEqual(resultingEvent.headers, expectedHeaders) + t.deepEqual(resultingEvent.rawHeaders, originalHeaders) +}) + // multiValueHeaders test('It should normalize (lowercase) all the headers and create a copy in rawMultiValueHeaders', async (t) => { @@ -184,6 +225,47 @@ test('It can use custom normalization function on multiValueHeaders', async (t) t.deepEqual(resultingEvent.rawMultiValueHeaders, originalHeaders) }) +test('It should normalize (lowercase) all the multiValueHeaders with defaults', async (t) => { + const handler = middy() + .use( + httpHeaderNormalizer({ + defaultHeaders: { + 'Content-Type': 'application/json', + Accept: '*/*' + } + }) + ) + .handler((event, context) => event) + + const event = { + multiValueHeaders: { + 'x-aPi-key': '123456', + tcn: 'abc', + te: 'cde', + DNS: 'd', + FOO: 'bar', + Accept: 'application/json' + } + } + + const expectedHeaders = { + 'x-api-key': '123456', + tcn: 'abc', + te: 'cde', + dns: 'd', + foo: 'bar', + accept: 'application/json', + 'content-type': 'application/json' + } + + const originalHeaders = { ...event.multiValueHeaders } + + const resultingEvent = await handler(event, context) + + t.deepEqual(resultingEvent.multiValueHeaders, expectedHeaders) + t.deepEqual(resultingEvent.rawMultiValueHeaders, originalHeaders) +}) + // Misc test('It should not fail if the event does not contain headers', async (t) => { const handler = middy((event, context) => event) diff --git a/packages/http-header-normalizer/index.d.ts b/packages/http-header-normalizer/index.d.ts index b28e0a03a..a55779da4 100644 --- a/packages/http-header-normalizer/index.d.ts +++ b/packages/http-header-normalizer/index.d.ts @@ -1,15 +1,16 @@ import middy from '@middy/core' interface Options { - normalizeHeaderKey?: (key: string) => string canonical?: boolean + defaultHeaders?: Record + normalizeHeaderKey?: (key: string) => string } export interface Event { rawHeaders: Record } -declare function httpHeaderNormalizer ( +declare function httpHeaderNormalizer( options?: Options ): middy.MiddlewareObj diff --git a/packages/http-header-normalizer/index.js b/packages/http-header-normalizer/index.js index 972dcdb23..a01ded82b 100644 --- a/packages/http-header-normalizer/index.js +++ b/packages/http-header-normalizer/index.js @@ -52,16 +52,23 @@ const normalizeHeaderKey = (key, canonical) => { const defaults = { canonical: false, + defaultHeaders: {}, normalizeHeaderKey } const httpHeaderNormalizerMiddleware = (opts = {}) => { const options = { ...defaults, ...opts } + const defaultHeaders = {} + for (const key of Object.keys(options.defaultHeaders)) { + defaultHeaders[options.normalizeHeaderKey(key, options.canonical)] = + options.defaultHeaders[key] + } + const httpHeaderNormalizerMiddlewareBefore = async (request) => { if (request.event.headers) { const rawHeaders = {} - const headers = {} + const headers = { ...defaultHeaders } for (const key of Object.keys(request.event.headers)) { rawHeaders[key] = request.event.headers[key] @@ -75,7 +82,7 @@ const httpHeaderNormalizerMiddleware = (opts = {}) => { if (request.event.multiValueHeaders) { const rawHeaders = {} - const headers = {} + const headers = { ...defaultHeaders } for (const key of Object.keys(request.event.multiValueHeaders)) { rawHeaders[key] = request.event.multiValueHeaders[key] diff --git a/website/docs/middlewares/http-event-normalizer.md b/website/docs/middlewares/http-event-normalizer.md index a5d84d866..b60670602 100644 --- a/website/docs/middlewares/http-event-normalizer.md +++ b/website/docs/middlewares/http-event-normalizer.md @@ -38,22 +38,3 @@ const handler = middy((event, context) => { handler.use(httpEventNormalizer()) ``` - -## Need to set default `Content-Type` of other missing headers? - -```javascript -import middy from '@middy/core' -import httpEventNormalizer from '@middy/http-event-normalizer' - -const handler = middy() - .before((request) => { - request.event.headers['Content-Type'] ??= 'application/json' - }) - .use(httpEventNormalizer()) - .handler((event, context) => { - console.log(`Hello user ${event.pathParameters.userId}`) - // might produce `Hello user undefined`, but not an error - - return {} - }) -``` diff --git a/website/docs/middlewares/http-header-normalizer.md b/website/docs/middlewares/http-header-normalizer.md index f685dc383..2dc8e4b5b 100644 --- a/website/docs/middlewares/http-header-normalizer.md +++ b/website/docs/middlewares/http-header-normalizer.md @@ -23,13 +23,12 @@ To install this middleware you can use NPM: npm install --save @middy/http-header-normalizer ``` - ## Options - - `normalizeHeaderKey` (function) (optional): a function that accepts an header name as a parameter and returns its +- `canonical` (bool) (optional): if true, modifies the headers to canonical format, otherwise the headers are normalized to lowercase (default `false`) +- `defaultHeaders` (object) (optional): Default headers to used if any are missing. i.e. `Content-Type` (default `{}`) +- `normalizeHeaderKey` (function) (optional): a function that accepts an header name as a parameter and returns its canonical representation. - - `canonical` (bool) (optional): if true, modifies the headers to canonical format, otherwise the headers are normalized to lowercase (default `false`) - ## Sample usage @@ -37,10 +36,9 @@ npm install --save @middy/http-header-normalizer import middy from '@middy/core' import httpHeaderNormalizer from '@middy/http-header-normalizer' -const handler = middy((event, context) => { - return {} -}) - -handler +const handler = middy() .use(httpHeaderNormalizer()) + .handler((event, context) => { + return {} + }) ```