From 8f1c9a2c4a6ee5ceb1de405437eb8d559ea15ac6 Mon Sep 17 00:00:00 2001 From: Michael Harrington Date: Tue, 16 Jul 2024 12:11:38 -0400 Subject: [PATCH 1/3] test: added test expecting request headers to get lowercased --- __tests__/integration.js | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/__tests__/integration.js b/__tests__/integration.js index f1c09a99..2e6ee91d 100644 --- a/__tests__/integration.js +++ b/__tests__/integration.js @@ -103,6 +103,40 @@ describe.each(EACH_MATRIX)('%s:%s: integration tests', (eventSourceName, framewo expect(response).toEqual(expectedResponse) }) + test('headers get lowercased', async () => { + app = express() + router = express.Router() + app.use('/', router) + serverlessExpressInstance = serverlessExpress({ app }) + router.get('/foo', (req, res) => { + const xHeaders = Object.fromEntries( + Object.entries(req.headers).filter(([name]) => name.startsWith('x-header-')) + ) + res.json({ xHeaders }) + }) + const event = makeEvent({ + eventSourceName: 'apiGatewayV1', + path: '/foo', + httpMethod: 'GET', + multiValueHeaders: undefined, + headers: { + 'X-Header-One': 'Value1', + 'x-header-two': 'Value2' + } + }) + const response = await serverlessExpressInstance(event) + const expectedResponse = makeResponse({ + eventSourceName: 'apiGatewayV1', + body: JSON.stringify({ + xHeaders: { + 'x-header-one': 'Value1', + 'x-header-two': 'Value2' + } + }) + }) + expect(response).toMatchObject(expectedResponse) + }) + test('resolutionMode = CALLBACK', (done) => { const jsonResponse = { data: { name: 'Brett' } } router.get('/users', (req, res) => { @@ -287,7 +321,7 @@ describe.each(EACH_MATRIX)('%s:%s: integration tests', (eventSourceName, framewo const response = await serverlessExpressInstance(event) const expectedResponse = makeResponse({ eventSourceName, - body: JSON.stringify({ data: { name: name } }), + body: JSON.stringify({ data: { name } }), multiValueHeaders: { 'content-length': ['29'], etag: ['W/"1d-9ERga12t1e/5eBdg3k9zfIvAfWo"'] From 8eb4a449bf94efd7080805cc1b75261abaf1896b Mon Sep 17 00:00:00 2001 From: Michael Harrington Date: Tue, 16 Jul 2024 12:13:01 -0400 Subject: [PATCH 2/3] fix: delegate to http.IncomingMessage for header lowercasing/aliasing logic --- src/request.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/request.js b/src/request.js index a50e45f3..451a843a 100644 --- a/src/request.js +++ b/src/request.js @@ -15,6 +15,11 @@ module.exports = class ServerlessRequest extends http.IncomingMessage { destroy: Function.prototype }) + // IncomingMessage has a lot of logic for when to lowercase or alias well-known header names, + // so we delegate to that logic here + const rawHeaders = Object.entries(headers).flat() + this._addHeaderLines(rawHeaders, rawHeaders.length) + Object.assign(this, { ip: remoteAddress, complete: true, @@ -22,7 +27,6 @@ module.exports = class ServerlessRequest extends http.IncomingMessage { httpVersionMajor: '1', httpVersionMinor: '1', method, - headers, body, url }) From bef14dcc33197d17671ee50977d5aadc3d862ae9 Mon Sep 17 00:00:00 2001 From: Michael Harrington Date: Tue, 16 Jul 2024 12:39:05 -0400 Subject: [PATCH 3/3] refactor: slight optimization since we know the size of the 2D headers array --- src/request.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/request.js b/src/request.js index 451a843a..53450c4e 100644 --- a/src/request.js +++ b/src/request.js @@ -17,7 +17,12 @@ module.exports = class ServerlessRequest extends http.IncomingMessage { // IncomingMessage has a lot of logic for when to lowercase or alias well-known header names, // so we delegate to that logic here - const rawHeaders = Object.entries(headers).flat() + const headerEntries = Object.entries(headers) + const rawHeaders = new Array(headerEntries.length * 2) + for (let i = 0; i < headerEntries.length; i++) { + rawHeaders[i * 2] = headerEntries[i][0] + rawHeaders[i * 2 + 1] = headerEntries[i][1] + } this._addHeaderLines(rawHeaders, rawHeaders.length) Object.assign(this, {