Skip to content

Commit dbb99a2

Browse files
author
Ethan Dave B. Gomez
committed
Merge branch 'release/1.4.0'
- Support for proxy request multiValueHeaders - Support for proxy request multiValueQueryStringParameters - Support for proxy isBase64Encoded
2 parents 4460aa0 + 654615b commit dbb99a2

File tree

6 files changed

+193
-123
lines changed

6 files changed

+193
-123
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 1.4.0
4+
5+
- Support for proxy request multiValueHeaders
6+
- Support for proxy request multiValueQueryStringParameters
7+
- Support for proxy isBase64Encoded
8+
39
## 1.3.0
410

511
- Fix escape

README.md

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# api-gateway-sim
2+
23
AWS API Gateway simulator for Node JS Lambda
34

45
Install
6+
57
```bash
68
$ npm install -g api-gateway-sim
79
```
@@ -13,23 +15,27 @@ Choose **"Export as Swagger + API Gateway Integrations"**.
1315
See details in [Export an API from Api Gateway](http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-export-api.html)
1416

1517
Running the simulator using **_ags_** cli
18+
1619
```bash
1720
$ cd <node lambda directory>
1821
$ ags --swagger <exported swagger json file>.json
1922

2023
```
2124

2225
Testing your lambda
26+
2327
```bash
2428
$ curl http://localhost:3000/
2529
```
2630

2731
Using different listening port
32+
2833
```bash
2934
$ PORT=4000 ags --swagger <file>.json
3035
```
3136

3237
Command Line Help
38+
3339
```bash
3440
Usage: ags [options]
3541

@@ -49,23 +55,24 @@ Command Line Help
4955
-g, --ags-port <port> AGS UI port, default 4000
5056
```
5157

52-
Features
53-
---------
58+
## Features
59+
60+
- Supports Body Mapping Templates
61+
- Supports Body Mapping Template validation.
5462

55-
* Supports Body Mapping Templates
56-
* Supports Body Mapping Template validation.
5763
```bash
5864
$ ags -a
5965

6066
# From your browser open http://localhost:4000
6167
```
62-
* Supports integration responses
63-
* Supports event.json, context.json, and stage-variables.json
64-
* Continues to monitoring changes in your lambda code. YES! No need to restart **_ags_**
65-
* Support for json or yaml swagger file.
66-
* Monitor changes in event.json, context.json, and stage-variables.json
67-
* CORS - enabled by default
68-
* Supports lambda timeout
69-
* Supports base path
70-
* Supports {proxy+}
7168

69+
- Supports integration responses
70+
- Supports event.json, context.json, and stage-variables.json
71+
- Continues to monitoring changes in your lambda code. YES! No need to restart **_ags_**
72+
- Support for json or yaml swagger file.
73+
- Monitor changes in event.json, context.json, and stage-variables.json
74+
- CORS - enabled by default
75+
- Supports lambda timeout
76+
- Supports base path
77+
- Supports {proxy+}
78+
- Supports proxy integration isBase64Encoded, multiValueHeaders, and multiValueQueryStringParameters

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "api-gateway-sim",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"description": "AWS API Gateway simulator for Node JS Lambda",
55
"main": "./api-gateway-sim.js",
66
"bin": {

src/api-gateway-sim.ts

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,6 @@ class ApiGatewaySim {
172172
console.log(message);
173173
}
174174

175-
private getQueryParams(request: Request) {
176-
const url = require('url');
177-
const url_parts = url.parse(request.url, true);
178-
const query = url_parts.query;
179-
return query;
180-
}
181-
182175
private getPassThroughTemplateContent() {
183176
const file = __dirname + '/templates/pass-through.vtl';
184177
return fs.readFileSync(file, 'utf8');
@@ -290,13 +283,37 @@ class ApiGatewaySim {
290283
}
291284
}
292285

286+
private setHeaders(bodyTemplate: BodyTemplate, request: Request) {
287+
const keys = Object.keys(request.headers);
288+
if (!bodyTemplate.headers) {
289+
bodyTemplate.headers = {};
290+
}
291+
for (const key of keys) {
292+
if (Array.isArray(request.headers[key])) {
293+
bodyTemplate.headers[key] =
294+
request.headers[key][request.headers[key].length - 1];
295+
bodyTemplate.multiValueHeaders[key] = request.headers[key];
296+
} else {
297+
bodyTemplate.headers[key] = request.headers[key];
298+
bodyTemplate.multiValueHeaders[key] = [request.headers[key]];
299+
}
300+
}
301+
}
302+
303+
private setQueryParams(bodyTemplate: BodyTemplate, request: Request) {
304+
const url = require('url');
305+
const url_parts = url.parse(request.url, true);
306+
const query = url_parts.query;
307+
bodyTemplate.queryParams = query;
308+
}
309+
293310
private parseEvent(method: Method, request: Request) {
294311
const bodyTemplate = new BodyTemplate();
295312
bodyTemplate.context = this.getContextJson();
296313
this.setContextDefaults(bodyTemplate.context, request);
297-
bodyTemplate.headers = request.headers;
314+
this.setHeaders(bodyTemplate, request);
298315
bodyTemplate.pathParams = this.getBodyTemplatePathParams(request);
299-
bodyTemplate.queryParams = this.getQueryParams(request);
316+
this.setQueryParams(bodyTemplate, request);
300317
bodyTemplate.method = request.method;
301318
bodyTemplate.payload = this.getBodyTemplatePayload(method, request);
302319
bodyTemplate.stageVariables = this.getStageVariables();
@@ -434,11 +451,30 @@ class ApiGatewaySim {
434451
return Object.keys(object).length === 0 && object.constructor === Object;
435452
}
436453

437-
private getProxyQueryString(request: Request) {
454+
private setProxyQueryString(event: any, request: Request) {
438455
if (this.isObjectEmpty(request.query)) {
439-
return null;
456+
event.queryStringParameters = null;
457+
event.multiValueQueryStringParameters = null;
458+
return;
459+
}
460+
if (!event.queryStringParameters) {
461+
event.queryStringParameters = {};
462+
}
463+
if (!event.multiValueQueryStringParameters) {
464+
event.multiValueQueryStringParameters = {};
465+
}
466+
const keys = Object.keys(request.query);
467+
const queries = request.query;
468+
for (const key of keys) {
469+
if (Array.isArray(queries[key])) {
470+
event.queryStringParameters[key] =
471+
queries[key][queries[key].length - 1];
472+
event.multiValueQueryStringParameters[key] = queries[key];
473+
} else {
474+
event.queryStringParameters[key] = queries[key];
475+
event.multiValueQueryStringParameters[key] = [queries[key]];
476+
}
440477
}
441-
return request.query;
442478
}
443479

444480
private processProxyData(
@@ -458,9 +494,7 @@ class ApiGatewaySim {
458494
request.originalUrl
459495
);
460496
requestObject.eventJson.headers = this.getRawHeaders(request);
461-
requestObject.eventJson.queryStringParameters = this.getProxyQueryString(
462-
request
463-
);
497+
this.setProxyQueryString(requestObject.eventJson, request);
464498
requestObject.eventJson.httpMethod = request.method;
465499
this.removeNonProxyFields(requestObject.eventJson);
466500
this.setProxyStageVariables(path, requestObject.eventJson, request);
@@ -567,6 +601,7 @@ class ApiGatewaySim {
567601
body: true,
568602
statusCode: true,
569603
headers: true,
604+
isBase64Encoded: true,
570605
multiValueHeaders: true
571606
};
572607
for (const property in message) {
@@ -614,6 +649,16 @@ class ApiGatewaySim {
614649
}
615650
}
616651

652+
private setBase64Encoded(method: Method, message: any) {
653+
if (
654+
method.integration &&
655+
method.integration.contentHandling === 'CONVERT_TO_BINARY'
656+
) {
657+
return Buffer.from(message.body, 'base64');
658+
}
659+
return message.body;
660+
}
661+
617662
private sendAwsProxyResponse(
618663
httpResponse: Response,
619664
method: Method,
@@ -640,6 +685,9 @@ class ApiGatewaySim {
640685
} else {
641686
this.setMessageStatusCode(httpResponse, message);
642687
this.setMessageHeaders(httpResponse, message);
688+
if (message.isBase64Encoded) {
689+
parseBody = this.setBase64Encoded(method, message);
690+
}
643691
this.sendDefaultResponse(httpResponse, method, parseBody);
644692
}
645693
} catch (error) {

0 commit comments

Comments
 (0)