Skip to content

Commit 15b9795

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents 6fdcad3 + 93544da commit 15b9795

File tree

3 files changed

+43
-42
lines changed

3 files changed

+43
-42
lines changed

src/lambda-wrapper.js

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ const { Request } = require('./request');
55
* API Gateway handler generator for Lambda
66
*
77
* @param {object} router Express compatible router instance
8-
* @param {function} finalHandler Process response before sending it. Function params: err, out, req, res
8+
* @param {function} onFinished Last callback before output gets send. Function params: out, req, res
99
* @return {function} Lambda handler for API gateway events
1010
* @public
1111
*/
1212

13-
exports.ApiGatewayHandler = (router, finalHandler) => {
13+
exports.ApiGatewayHandler = (router, onFinished) => {
1414
/**
1515
* Lambda Handler for API Gateway invocations
1616
*
@@ -19,28 +19,28 @@ exports.ApiGatewayHandler = (router, finalHandler) => {
1919
* @return {promise} Returns undefined if callback param is set. Return a promise if callback param is undefined.
2020
*/
2121
return handleApiGatewayEvent = (event, context) => {
22-
return new Promise((resolve, reject) => {
23-
try {
24-
const req = new Request(event);
25-
const res = req.res = new Response(req, out => {
26-
resolve(finalHandler(null, out, req, res))
27-
});
28-
29-
// run middleware managed by router
30-
router(req, res, async err => {
31-
if (err) {
32-
// unexpected errors should be handled by final handler
33-
resolve(finalHandler(err, null, req, res))
34-
} else if (res.writableEnded) {
35-
console.error('ERROR: next() should not be used after res.send() within routing middleware');
36-
} else {
37-
// expected error
38-
res.status(404).send('Not found');
39-
}
40-
})
41-
} catch (error) {
42-
resolve(finalHandler(error, null, null, null))
43-
}
22+
return new Promise(resolve => {
23+
const req = new Request(event);
24+
const res = req.res = new Response(req, async out => {
25+
// run and wait for onFinished callback
26+
if (onFinished) try {
27+
out = await onFinished(out, req, res)
28+
} catch (err) {
29+
console.error('Error in onFinished callback: ', err)
30+
}
31+
// resolve promise even if onFinished callback errors out
32+
resolve(out)
33+
});
34+
router(req, res, err => {
35+
// handle generic routing errors
36+
// use error handling middleware for more granular control
37+
if (err) {
38+
console.error('ERROR: ', err)
39+
res.status(500).send('Server error')
40+
} else {
41+
res.status(404).send('Not found');
42+
}
43+
})
4444
})
4545
}
46-
}
46+
}

src/lambda-wrapper.spec.js

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@ const { ApiGatewayHandler } = require('./lambda-wrapper');
22
const Router = require('router');
33
const bodyParser = require('body-parser');
44

5-
function finalHandlerPassTrough (err, out, req, res) {
6-
return out
7-
}
8-
95
describe('Lambda Wrapper', () => {
106
const proxyRequest = {
117
body: null,
@@ -28,7 +24,7 @@ describe('Lambda Wrapper', () => {
2824
router.use((req, res) => {
2925
res.json({a: 1});
3026
})
31-
const lambdaHandler = ApiGatewayHandler(router, finalHandlerPassTrough);
27+
const lambdaHandler = ApiGatewayHandler(router);
3228
const proxyRequest = {
3329
body: '',
3430
headers: {},
@@ -63,7 +59,7 @@ describe('Lambda Wrapper', () => {
6359
router.use((req, res) => {
6460
res.json(req.body);
6561
})
66-
const lambdaHandler = ApiGatewayHandler(router, finalHandlerPassTrough);
62+
const lambdaHandler = ApiGatewayHandler(router);
6763

6864
const requestObject = JSON.stringify({a: 1});
6965
const proxyRequest = {
@@ -108,7 +104,7 @@ describe('Lambda Wrapper', () => {
108104
router.use((req, res) => {
109105
res.json({b: req.fromFirstEndpoint});
110106
})
111-
const lambdaHandler = ApiGatewayHandler(router, finalHandlerPassTrough);
107+
const lambdaHandler = ApiGatewayHandler(router);
112108

113109
const result = await lambdaHandler(proxyRequest, {});
114110

@@ -128,11 +124,13 @@ describe('Lambda Wrapper', () => {
128124
router.use((req, res, next) => {
129125
throw Error('test');
130126
})
131-
132-
const lambdaHandler2 = ApiGatewayHandler(router, err => {
127+
router.use((err, req, res, next) => {
133128
expect(err).toEqual(Error('test'));
129+
next();
134130
})
135-
await lambdaHandler2(proxyRequest, {})
131+
const lambdaHandler = ApiGatewayHandler(router)
132+
const out = await lambdaHandler(proxyRequest, {})
133+
console.log(out)
136134
})
137135

138136
it('should handle next(error)', async () => {
@@ -142,11 +140,12 @@ describe('Lambda Wrapper', () => {
142140
router.use((req, res, next) => {
143141
next('test');
144142
})
145-
const lambdaHandler = ApiGatewayHandler(router, err => {
143+
router.use((err, req, res, next) => {
146144
expect(err).toEqual('test');
147-
});
145+
next();
146+
})
147+
const lambdaHandler = ApiGatewayHandler(router);
148148
await lambdaHandler(proxyRequest, {})
149-
150149
})
151150

152151
it('GET with path', async () => {
@@ -160,7 +159,7 @@ describe('Lambda Wrapper', () => {
160159
res.json({a: req.fromFirstEndpoint, b: 2});
161160
});
162161

163-
const lambdaHandler = ApiGatewayHandler(router, finalHandlerPassTrough);
162+
const lambdaHandler = ApiGatewayHandler(router);
164163
const proxyRequest = {
165164
body: '',
166165
headers: {},
@@ -199,7 +198,7 @@ describe('Lambda Wrapper', () => {
199198
res.json({a: req.foo, b: 2});
200199
});
201200

202-
const lambdaHandler = ApiGatewayHandler(router, finalHandlerPassTrough);
201+
const lambdaHandler = ApiGatewayHandler(router);
203202

204203
const result = await lambdaHandler(proxyRequest, {});
205204
expect(result).toEqual({
@@ -223,7 +222,7 @@ describe('Lambda Wrapper', () => {
223222
const router = Router()
224223
router.use('/testing', subRouter)
225224

226-
const lambdaHandler = ApiGatewayHandler(router, finalHandlerPassTrough);
225+
const lambdaHandler = ApiGatewayHandler(router);
227226

228227
let request = {}
229228
Object.assign(request, proxyRequest)

src/response.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ class Response extends EventEmitter {
3333
if (this.writableEnded) throw new Error('write after end')
3434
this.writableEnded = true
3535
this.emit('finished')
36+
const body = this[AWS_RES_BODY]
37+
const bodyStr = typeof body === 'string' ? body : JSON.stringify(body)
3638
const apiGatewayResult = {
3739
statusCode: this.statusCode,
3840
headers: this[AWS_RES_HEADERS],
39-
body: this[AWS_RES_BODY]
41+
body: bodyStr
4042
}
4143
this[ON_FINISHED](apiGatewayResult)
4244
}

0 commit comments

Comments
 (0)