Skip to content
This repository was archived by the owner on Aug 8, 2024. It is now read-only.

Commit 640d5eb

Browse files
authored
improve documenation for proxyPath + add tests (#32)
1 parent 4fbf4bf commit 640d5eb

File tree

4 files changed

+198
-29
lines changed

4 files changed

+198
-29
lines changed

README.md

Lines changed: 89 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1+
12
# AWS Lambda Router [![Build Status](https://travis-ci.org/spring-media/aws-lambda-router.svg?branch=master)](https://travis-ci.org/spring-media/aws-lambda-router)
23

3-
[![codecov](https://codecov.io/gh/spring-media/aws-lambda-router/branch/master/graph/badge.svg)](https://codecov.io/gh/spring-media/aws-lambda-router)
4-
[![npm version](https://badge.fury.io/js/aws-lambda-router.svg)](https://badge.fury.io/js/aws-lambda-router)
5-
[![dependencies](https://david-dm.org/spring-media/aws-lambda-router.svg)](https://www.npmjs.com/package/aws-lambda-router)
4+
[![codecov](https://codecov.io/gh/spring-media/aws-lambda-router/branch/master/graph/badge.svg)](https://codecov.io/gh/spring-media/aws-lambda-router) [![npm version](https://badge.fury.io/js/aws-lambda-router.svg)](https://badge.fury.io/js/aws-lambda-router) [![dependencies](https://david-dm.org/spring-media/aws-lambda-router.svg)](https://www.npmjs.com/package/aws-lambda-router)
65

76

87

9-
A small library for [AWS Lambda](https://aws.amazon.com/lambda/details) providing routing for [API Gateway](https://aws.amazon.com/api-gateway),
10-
[Proxy Integrations](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html), [SNS](https://aws.amazon.com/sns)
11-
and [S3 Events](https://docs.aws.amazon.com/AmazonS3/latest/dev/notification-content-structure.html).
8+
A small library for [AWS Lambda](https://aws.amazon.com/lambda/details) providing routing for [API Gateway](https://aws.amazon.com/api-gateway), [Proxy Integrations](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html), [SNS](https://aws.amazon.com/sns) and [S3 Events](https://docs.aws.amazon.com/AmazonS3/latest/dev/notification-content-structure.html).
129

1310
## Features
1411

@@ -17,7 +14,11 @@ and [S3 Events](https://docs.aws.amazon.com/AmazonS3/latest/dev/notification-con
1714
* Lambda Proxy Resource support for AWS API Gateway
1815
* Enable CORS for requests
1916
* No external dependencies
20-
* Currently there are four `processors` (callers for Lambda) implemented: API Gateway ANY method (called proxyIntegration), SNS, SQS and S3.
17+
* Currently there are four `processors` (callers for Lambda) implemented:
18+
* API Gateway ANY method (called proxyIntegration)
19+
* SNS
20+
* SQS
21+
* S3
2122

2223
## Installation
2324

@@ -34,13 +35,12 @@ $ yarn add aws-lambda-router
3435

3536
## Getting Started
3637

37-
This is a simple example of `aws-lambda-router` in conjunction with ANY method and the API Gateway proxy integration. The following code will respond with a message when executed using an AWS API Gateway with a `GET` request on URL path `<base-url-of-gateway>/gateway-mapping/article/123`.
38+
This is a simple example of `aws-lambda-router` in conjunction with ANY method and the API Gateway proxy integration. The following code will respond with a message when executed using an AWS API Gateway with a `GET` request on URL path `<base-url-of-gateway>/gateway-mapping/article/123`. The corresponding AWS API Gateway Resource is `/article/{articleId}`.
3839

3940
```js
40-
import * as router from 'aws-lambda-router'
41+
import * as router from 'aws-lambda-router'
4142

4243
export const handler = router.handler({
43-
// for handling an http-call from an AWS API Gateway proxyIntegration we provide the following config:
4444
proxyIntegration: {
4545
routes: [
4646
{
@@ -57,6 +57,45 @@ export const handler = router.handler({
5757
}
5858
```
5959
60+
## Proxy path support (work in progress)
61+
62+
The proxy integration usually works using a path configured in the API gateway. For example: `/article/{id}`.
63+
64+
If you use the WIP *proxy path support*, the complete path will be used to match a route config in `proxyIntegration`. This can be used to build an [Simple Proxy with API Gateway]([https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-http.html](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-http.html))
65+
66+
Example:
67+
* Resource in API Gateway : /{proxy+}
68+
* Method: ANY
69+
70+
With the lambda configuration shown below the following paths are matched:
71+
* _api-gateway-host_/article/list
72+
* _api-gateway-host_/api/json/v1/schema
73+
74+
```js
75+
const router = require('aws-lambda-router');
76+
77+
exports.handler = router.handler({
78+
proxyIntegration: {
79+
proxyPath: proxy
80+
routes: [
81+
{
82+
path: '/article/list',
83+
method: 'GET',
84+
action: (request, context) => {
85+
return "You called me with: " + request.path;
86+
}
87+
},
88+
{
89+
path: '/api/json/v1/schema',
90+
method: 'GET',
91+
action: (request, context) => {
92+
return "You called me with: " + request.path;
93+
}
94+
}
95+
]
96+
}
97+
}
98+
```
6099
61100
## Enable CORS
62101
@@ -66,7 +105,7 @@ See the following example:
66105
67106
68107
```js
69-
import * as router from 'aws-lambda-router'
108+
import * as router from 'aws-lambda-router'
70109

71110
export const handler = router.handler({
72111
// for handling an http-call from an AWS Apigateway proxyIntegration we provide the following config:
@@ -91,10 +130,10 @@ If CORS is activated, these default headers will be sent on every response:
91130
"Access-Control-Allow-Headers" = "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
92131
93132
94-
## Errormapping
133+
## Error mapping
95134
96135
```js
97-
import * as router from 'aws-lambda-router'
136+
import * as router from 'aws-lambda-router'
98137

99138
export const handler = router.handler({
100139
// for handling an http-call from an AWS Apigateway proxyIntegration we provide the following config:
@@ -135,7 +174,7 @@ SNS Event Structure: https://docs.aws.amazon.com/sns/latest/dg/sns-message-and-j
135174
For handling calls in Lambdas initiated from AWS-SNS you can use the following code snippet:
136175
137176
```js
138-
import * as router from 'aws-lambda-router'
177+
import * as router from 'aws-lambda-router'
139178

140179
export const handler = router.handler({
141180
sns: {
@@ -156,7 +195,7 @@ export const handler = router.handler({
156195
For handling calls in Lambdas initiated from AWS-SQS you can use the following code snippet:
157196
158197
```js
159-
import * as router from 'aws-lambda-router'
198+
import * as router from 'aws-lambda-router'
160199

161200
export const handler = router.handler({
162201
sqs: {
@@ -200,7 +239,7 @@ The action method will be called with the records of the [S3Event Structure](htt
200239
The following examples demonstrates the most use cases:
201240
202241
```js
203-
import * as router from 'aws-lambda-router'
242+
import * as router from 'aws-lambda-router'
204243

205244
export const handler = router.handler({
206245
s3: {
@@ -290,16 +329,37 @@ See here: https://yarnpkg.com/en/docs/cli/link
290329
291330
## Release History
292331
293-
* 0.7.0 migrate to typescript; using aws-lambda typings; proxyIntegration: cors is now optional (default: false);
294-
* 0.6.2 take away old gulp dependency to run tests, works now with scripts in package.json; normalize request path to start from local host (thanks to [@napicella](https://github.com/napicella))
295-
* 0.6.1 s3: fix: aggregate result promises to one promise; fix: s3Route interface
296-
* 0.6.0 new feature: S3 routes available.
297-
* 0.5.0 new feature: SQS route integration now available; bugfix: SNS integration now works with Array of message instead of single message
298-
* 0.4.0 now [the Context Object](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html) pass through
299-
* 0.3.1 proxyIntegration: avoid error if response object is not set; add some debug logging
300-
* 0.3.0 proxyIntegration: add PATCH method; allow for custom status codes from route (thanks to [@mintuz](https://github.com/mintuz))
301-
* 0.2.2 proxyIntegration: set correct header values now for CORS
302-
* 0.2.1 proxyIntegration: CORS in Preflight, status code 400 for invalid body, set more CORS headers as default
303-
* 0.2.0 Attention: breaking changes for configuration; add SNS event process
304-
* 0.1.0 make it work now
305-
* 0.0.1 initial release
332+
* 0.7.0
333+
* migrate to typescript
334+
* using aws-lambda typings
335+
* proxyIntegration: cors is now optional (default: false)
336+
* experimental _proxy path support_ (thanks to [@swaner](https://github.com/swaner))
337+
* 0.6.2
338+
* take away old gulp dependency to run tests, works now with scripts in package.json
339+
* normalize request path to start from local host (thanks to [@napicella](https://github.com/napicella))
340+
* 0.6.1
341+
* s3: fix: aggregate result promises to one promise;
342+
* s3: s3Route interface
343+
* 0.6.0
344+
* new feature: S3 routes available.
345+
* 0.5.0
346+
* new feature: SQS route integration now available;
347+
* bugfix: SNS integration now works with Array of message instead of single message
348+
* 0.4.0
349+
* now [the Context Object](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html) pass through
350+
* 0.3.1 proxyIntegration:
351+
* avoid error if response object is not set;
352+
* add some debug logging
353+
* 0.3.0
354+
* proxyIntegration: add PATCH method;
355+
* allow for custom status codes from route (thanks to [@mintuz](https://github.com/mintuz))
356+
* 0.2.2
357+
* proxyIntegration: set correct header values now for CORS
358+
* 0.2.1
359+
* proxyIntegration: CORS in Preflight, status code 400 for invalid body, set more CORS headers as default
360+
* 0.2.0 *Attention*: breaking changes for configuration;
361+
* add SNS event process
362+
* 0.1.0
363+
* make it work now
364+
* 0.0.1
365+
* initial release

lib/proxyIntegration.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ export const process: ProcessMethod<ProxyIntegrationConfig, ProxyIntegrationEven
112112
errorMapping['NO_MATCHING_ACTION'] = 404;
113113

114114
if (proxyIntegrationConfig.proxyPath) {
115+
console.log("proxy path is set: " + proxyIntegrationConfig.proxyPath)
115116
event.path = (event.pathParameters || {})[proxyIntegrationConfig.proxyPath];
117+
console.log("proxy path with event path: " + event.path)
118+
116119
} else {
117120
event.path = normalizeRequestPath(event);
118121
}

test/proxyIntegration-example.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{ "resource": "/{proxy+}",
2+
"path": "/article/id/123",
3+
"httpMethod": "GET",
4+
"headers": null,
5+
"multiValueHeaders": null,
6+
"queryStringParameters": null,
7+
"multiValueQueryStringParameters": null,
8+
"pathParameters": { "proxy": "/article/id/123" },
9+
"stageVariables": null,
10+
"requestContext":
11+
{ "resourceId": "1ykadr",
12+
"resourcePath": "/{path+}",
13+
"httpMethod": "GET",
14+
"extendedRequestId": "CUdEOHguFiAFu7g=",
15+
"requestTime": "29/Oct/2019:10:05:27 +0000",
16+
"path": "/{path+}",
17+
"accountId": "272144222552",
18+
"protocol": "HTTP/1.1",
19+
"stage": "test-invoke-stage",
20+
"domainPrefix": "testPrefix",
21+
"requestTimeEpoch": 1572343527768,
22+
"requestId": "5e2ae356-64d0-4b9c-a25e-a57c7902128e",
23+
"identity":
24+
{ "cognitoIdentityPoolId": null,
25+
"cognitoIdentityId": null,
26+
"apiKey": "test-invoke-api-key",
27+
"principalOrgId": null,
28+
"cognitoAuthenticationType": null,
29+
"userArn": "arn:aws:iam::272144222552:user/christian.gohlke",
30+
"apiKeyId": "test-invoke-api-key-id",
31+
"userAgent": "aws-internal/3 aws-sdk-java/1.11.648 Linux/4.9.184-0.1.ac.235.83.329.metal1.x86_64 OpenJDK_64-Bit_Server_VM/25.222-b10 java/1.8.0_222 vendor/Oracle_Corporation",
32+
"accountId": "272144222552",
33+
"caller": "AIDAILF7A6IE7C62DPESO",
34+
"sourceIp": "test-invoke-source-ip",
35+
"accessKey": "ASIAT6XIPJFMHGSWDU6C",
36+
"cognitoAuthenticationProvider": null,
37+
"user": "AIDAILF7A6IE7C62DPESO" },
38+
"domainName": "testPrefix.testDomainName",
39+
"apiId": "vkjrwsy9fl" },
40+
"body": null,
41+
"isBase64Encoded": false }

test/proxyIntegration.test.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// helper for parameterized tests (http://blog.piotrturski.net/2015/04/jasmine-parameterized-tests.html)
2+
import {log} from "util";
3+
24
function forEach(arrayOfArrays: any) {
35
return {
46
it: (description: string, testCaseFunction: (...args: any[]) => void | Promise<void>) => {
@@ -380,6 +382,69 @@ describe('proxyIntegration.routeHandler', () => {
380382
})
381383
})
382384

385+
describe('proxyIntegration.proxyPath', () => {
386+
387+
it('single proxy path', async () => {
388+
const spiedAction = jasmine.createSpy('action').and.returnValue({ })
389+
const routeConfig: ProxyIntegrationConfig = {
390+
proxyPath: 'apiPath',
391+
routes: [
392+
{
393+
method: 'GET',
394+
path: '/article/list',
395+
action: spiedAction
396+
}
397+
]
398+
}
399+
400+
const result = await proxyIntegration(routeConfig, { resource: "/{apiPath+}",
401+
path: "/article/list",
402+
pathParameters: { apiPath: "/article/list" },
403+
httpMethod: 'GET' } as any, context)
404+
405+
expect(spiedAction).toHaveBeenCalledWith({ resource: "/{apiPath+}", paths: {}, path: "/article/list", httpMethod: 'GET', pathParameters: { apiPath: "/article/list" } }, context)
406+
expect(result).toEqual({
407+
statusCode: 200,
408+
body: '{}',
409+
headers: Object.assign({ "Content-Type": "application/json" })
410+
})
411+
412+
})
413+
414+
it('multiple proxy path', async () => {
415+
const articleAction = jasmine.createSpy('action').and.returnValue({ })
416+
const sectionAction = jasmine.createSpy('action').and.returnValue({ })
417+
const routeConfig: ProxyIntegrationConfig = {
418+
proxyPath: 'apiPath',
419+
routes: [
420+
{
421+
method: 'GET',
422+
path: '/article/list',
423+
action: articleAction
424+
},
425+
{
426+
method: 'GET',
427+
path: '/section/list',
428+
action: sectionAction
429+
}
430+
]
431+
}
432+
await proxyIntegration(routeConfig, { resource: "/{apiPath+}",
433+
path: "/article/list",
434+
pathParameters: { apiPath: "/article/list" },
435+
httpMethod: 'GET' } as any, context)
436+
expect(articleAction).toHaveBeenCalledWith({ resource: "/{apiPath+}", paths: {}, path: "/article/list", httpMethod: 'GET', pathParameters: { apiPath: "/article/list" } }, context)
437+
expect(sectionAction).not.toHaveBeenCalled()
438+
439+
await proxyIntegration(routeConfig, { resource: "/{apiPath+}",
440+
path: "/section/list",
441+
pathParameters: { apiPath: "/section/list" },
442+
httpMethod: 'GET' } as any, context)
443+
expect(sectionAction).toHaveBeenCalledWith({ resource: "/{apiPath+}", paths: {}, path: "/section/list", httpMethod: 'GET', pathParameters: { apiPath: "/section/list" } }, context)
444+
445+
})
446+
})
447+
383448
describe('proxyIntegration.routeHandler.returnvalues', () => {
384449
it('should return async result with custom response object', async () => {
385450

0 commit comments

Comments
 (0)