Skip to content

Commit c25a39d

Browse files
authored
Alb multivalueheaders (#272)
* fix: ALB ignore headers property when multi value headers is on * ensure ret headers are arrays
1 parent 0679881 commit c25a39d

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ $ npm i @fastify/aws-lambda
2929
| decorationPropertyName | The default property name for request decoration | `awsLambda` |
3030
| callbackWaitsForEmptyEventLoop | See: [Official Documentation](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-context.html#nodejs-prog-model-context-properties) | `undefined` |
3131
| retainStage | Retain the stage part of the API Gateway URL | `false` |
32-
| pathParameterUsedAsPath | Use a defined pathParameter as path (i.e. `'proxy'`) | `false` |
33-
| parseCommaSeparatedQueryParams | Parse querystring with commas into an array of values. Affects the behavior of the querystring parser with commas while using [Payload Format Version 2.0](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format) | `true` |
34-
| payloadAsStream | If set to true the response is a stream and can be used with `awslambda.streamifyResponse` | `false` |
32+
| pathParameterUsedAsPath | Use a defined pathParameter as path (i.e. `'proxy'`) | `false` |
33+
| parseCommaSeparatedQueryParams | Parse querystring with commas into an array of values. Affects the behavior of the querystring parser with commas while using [Payload Format Version 2.0](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format) | `true` |
34+
| payloadAsStream | If set to true the response is a stream and can be used with `awslambda.streamifyResponse` | `false` |
35+
| albMultiValueHeaders | Set to true if using ALB with multi value headers attribute | `false` |
3536
## 📖Example
3637

3738
### lambda.js

index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ module.exports = (app, options) => {
1919
options.pathParameterUsedAsPath = options.pathParameterUsedAsPath !== undefined ? options.pathParameterUsedAsPath : false
2020
options.parseCommaSeparatedQueryParams = options.parseCommaSeparatedQueryParams !== undefined ? options.parseCommaSeparatedQueryParams : true
2121
options.payloadAsStream = options.payloadAsStream !== undefined ? options.payloadAsStream : false
22+
options.albMultiValueHeaders = options.albMultiValueHeaders !== undefined ? options.albMultiValueHeaders : false
2223
let currentAwsArguments = {}
2324
if (options.decorateRequest) {
2425
options.decorationPropertyName = options.decorationPropertyName || 'awsLambda'
@@ -80,6 +81,8 @@ module.exports = (app, options) => {
8081
Object.keys(event.multiValueHeaders).forEach((h) => {
8182
if (event.multiValueHeaders[h].length > 1) {
8283
headers[h] = event.multiValueHeaders[h]
84+
} else if (event.multiValueHeaders[h].length === 1 && options.albMultiValueHeaders) {
85+
headers[h] = event.multiValueHeaders[h][0]
8386
}
8487
})
8588
}
@@ -168,6 +171,12 @@ module.exports = (app, options) => {
168171

169172
if (cookies && event.version === '2.0') ret.cookies = cookies
170173
if (multiValueHeaders && (!event.version || event.version === '1.0')) ret.multiValueHeaders = multiValueHeaders
174+
if (options.albMultiValueHeaders) {
175+
if (!ret.multiValueHeaders) ret.multiValueHeaders = {}
176+
Object.entries(ret.headers).forEach(([key, value]) => {
177+
ret.multiValueHeaders[key] = [value]
178+
})
179+
}
171180

172181
if (!options.payloadAsStream) {
173182
ret.body = isBase64Encoded ? res.rawPayload.toString('base64') : res.payload

test/alb.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,4 +214,35 @@ describe('ALB Tests', async () => {
214214
assert.equal(ret.statusCode, 200)
215215
assert.equal(ret.body, '{"q$":["foo@bar","foo?bar"]}')
216216
})
217+
218+
it('GET with multi-value headers', async () => {
219+
const app = fastify()
220+
app.get('/test', async (request, reply) => {
221+
assert.equal(request.headers['x-my-header'], 'wuuusaaa')
222+
reply.send({ hello: 'world' })
223+
})
224+
const proxy = awsLambdaFastify(app, {
225+
albMultiValueHeaders: true
226+
})
227+
228+
const ret = await proxy({
229+
requestContext: { elb: { targetGroupArn: 'xxx' } },
230+
httpMethod: 'GET',
231+
path: '/test',
232+
multiValueHeaders: {
233+
'x-my-header': ['wuuusaaa']
234+
}
235+
})
236+
assert.equal(ret.statusCode, 200)
237+
assert.equal(ret.body, '{"hello":"world"}')
238+
console.log(JSON.stringify(ret.multiValueHeaders))
239+
assert.ok(ret.multiValueHeaders)
240+
assert.equal(
241+
ret.headers['content-type'],
242+
['application/json; charset=utf-8']
243+
)
244+
assert.equal(ret.headers['content-length'], ['17'])
245+
assert.ok(ret.headers.date)
246+
assert.equal(ret.headers.connection, ['keep-alive'])
247+
})
217248
})

0 commit comments

Comments
 (0)