Skip to content

Commit 4ccb68b

Browse files
author
Thorkil Holm-Jacobsen
authored
Add option to retain the API Gateway stage in the URL passed to fastify (#164)
* adds option to retain stage part of the url * added test for retain stage
1 parent e57ebf6 commit 4ccb68b

File tree

5 files changed

+55
-10
lines changed

5 files changed

+55
-10
lines changed

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ $ npm i @fastify/aws-lambda
2020

2121
**@fastify/aws-lambda** can take options by passing them with : `awsLambdaFastify(app, options)`
2222

23-
| property | description | default value |
24-
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ------------- |
25-
| binaryMimeTypes | Array of binary MimeTypes to handle | `[]` |
26-
| enforceBase64 | Function that receives the response and returns a boolean indicating if the response content is binary or not and should be base64-encoded | `undefined` |
27-
| serializeLambdaArguments | Activate the serialization of lambda Event and Context in http header `x-apigateway-event` `x-apigateway-context` | `false` *(was `true` for <v2.0.0)* |
28-
| decorateRequest | Decorates the fastify request with the lambda Event and Context `request.awsLambda.event` `request.awsLambda.context` | `true` |
29-
| decorationPropertyName | The default property name for request decoration | `awsLambda` |
30-
| callbackWaitsForEmptyEventLoop | See: [Official Documentation](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-context.html#nodejs-prog-model-context-properties) | `undefined` |
23+
| property | description | default value |
24+
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------- |
25+
| binaryMimeTypes | Array of binary MimeTypes to handle | `[]` |
26+
| enforceBase64 | Function that receives the response and returns a boolean indicating if the response content is binary or not and should be base64-encoded | `undefined` |
27+
| serializeLambdaArguments | Activate the serialization of lambda Event and Context in http header `x-apigateway-event` `x-apigateway-context` | `false` *(was `true` for <v2.0.0)* |
28+
| decorateRequest | Decorates the fastify request with the lambda Event and Context `request.awsLambda.event` `request.awsLambda.context` | `true` |
29+
| decorationPropertyName | The default property name for request decoration | `awsLambda` |
30+
| callbackWaitsForEmptyEventLoop | See: [Official Documentation](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-context.html#nodejs-prog-model-context-properties) | `undefined` |
31+
| retainStage | Retain the stage part of the API Gateway URL | `false` |
3132

3233
## 📖Example
3334

index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ module.exports = (app, options) => {
1515
options.binaryMimeTypes = options.binaryMimeTypes || []
1616
options.serializeLambdaArguments = options.serializeLambdaArguments !== undefined ? options.serializeLambdaArguments : false
1717
options.decorateRequest = options.decorateRequest !== undefined ? options.decorateRequest : true
18+
options.retainStage = options.retainStage !== undefined ? options.retainStage : false
1819
let currentAwsArguments = {}
1920
if (options.decorateRequest) {
2021
options.decorationPropertyName = options.decorationPropertyName || 'awsLambda'
@@ -40,8 +41,8 @@ module.exports = (app, options) => {
4041
const method = event.httpMethod || (event.requestContext && event.requestContext.http ? event.requestContext.http.method : undefined)
4142
let url = event.path || event.rawPath || '/' // seen rawPath for HTTP-API
4243
// NOTE: if used directly via API Gateway domain and /stage
43-
if (event.requestContext && event.requestContext.stage && event.requestContext.resourcePath &&
44-
(url).indexOf(`/${event.requestContext.stage}/`) === 0 &&
44+
if (!options.retainStage && event.requestContext && event.requestContext.stage &&
45+
event.requestContext.resourcePath && (url).indexOf(`/${event.requestContext.stage}/`) === 0 &&
4546
event.requestContext.resourcePath.indexOf(`/${event.requestContext.stage}/`) !== 0) {
4647
url = url.substring(event.requestContext.stage.length + 1)
4748
}

test/basic.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,36 @@ test('subpath', async (t) => {
351351
t.same(ret.multiValueHeaders['set-cookie'], ['qwerty=one', 'qwerty=two'])
352352
})
353353

354+
test('subpath retain stage', async (t) => {
355+
t.plan(7)
356+
357+
const app = fastify()
358+
app.get('/dev/test', async (request, reply) => {
359+
t.equal(request.headers['x-my-header'], 'wuuusaaa')
360+
t.equal(request.headers['x-apigateway-event'], '%7B%22httpMethod%22%3A%22GET%22%2C%22path%22%3A%22%2Fdev%2Ftest%22%2C%22headers%22%3A%7B%22X-My-Header%22%3A%22wuuusaaa%22%7D%2C%22requestContext%22%3A%7B%22resourcePath%22%3A%22%2Ftest%22%2C%22stage%22%3A%22dev%22%7D%7D')
361+
t.equal(request.headers['user-agent'], 'lightMyRequest')
362+
t.equal(request.headers.host, 'localhost:80')
363+
t.equal(request.headers['content-length'], '0')
364+
reply.header('Set-Cookie', 'qwerty=one')
365+
reply.header('Set-Cookie', 'qwerty=two')
366+
reply.send({ hello: 'world' })
367+
})
368+
const proxy = awsLambdaFastify(app, { retainStage: true, serializeLambdaArguments: true })
369+
const ret = await proxy({
370+
httpMethod: 'GET',
371+
path: '/dev/test',
372+
headers: {
373+
'X-My-Header': 'wuuusaaa'
374+
},
375+
requestContext: {
376+
resourcePath: '/test',
377+
stage: 'dev'
378+
}
379+
})
380+
t.equal(ret.statusCode, 200)
381+
t.equal(ret.body, '{"hello":"world"}')
382+
})
383+
354384
test('serializeLambdaArguments = false', async (t) => {
355385
t.plan(14)
356386

types/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ declare namespace awsLambdaFastify {
1111
decorateRequest?: boolean;
1212
decorationPropertyName?: string;
1313
enforceBase64?: (response: LightMyRequestResponse) => boolean;
14+
retainStage?: boolean;
1415
}
1516

1617
export interface LambdaResponse {

types/index.test-d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ expectAssignable<LambdaFastifyOptions>({
7575
return false;
7676
},
7777
});
78+
expectAssignable<LambdaFastifyOptions>({
79+
binaryMimeTypes: ["foo", "bar"],
80+
callbackWaitsForEmptyEventLoop: true,
81+
serializeLambdaArguments: false,
82+
decorateRequest: true,
83+
decorationPropertyName: "myAWSstuff",
84+
enforceBase64: (response) => {
85+
expectType<LightMyRequestResponse>(response);
86+
return false;
87+
},
88+
retainStage: true,
89+
});
7890

7991
expectError(awsLambdaFastify());
8092
expectError(awsLambdaFastify(app, { neh: "definition" }));

0 commit comments

Comments
 (0)