Skip to content

Commit 62126d7

Browse files
committed
Move to AWS Lambda promise syntax
1 parent 6356e4f commit 62126d7

File tree

2 files changed

+63
-73
lines changed

2 files changed

+63
-73
lines changed

src/index.spec.ts

Lines changed: 38 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -29,53 +29,45 @@ describe("servie-lambda", () => {
2929
memoryLimitInMB: "128"
3030
} as any) as Context;
3131

32-
it("should support routers", done => {
32+
it("should support routers", async () => {
3333
const handler = createHandler(function() {
3434
return new Response("response", {
3535
status: 200
3636
});
3737
});
3838

39-
return handler(event, context, (err, res) => {
40-
if (err) return done(err);
39+
const res = await handler(event, context);
4140

42-
expect(res).toEqual({
43-
statusCode: 200,
44-
body: "response",
45-
multiValueHeaders: {
46-
"content-type": ["text/plain"],
47-
"content-length": ["8"]
48-
},
49-
isBase64Encoded: false
50-
});
51-
52-
return done();
41+
expect(res).toEqual({
42+
statusCode: 200,
43+
body: "response",
44+
multiValueHeaders: {
45+
"content-type": ["text/plain"],
46+
"content-length": ["8"]
47+
},
48+
isBase64Encoded: false
5349
});
5450
});
5551

56-
it("should fall through to 404", done => {
52+
it("should fall through to 404", async () => {
5753
const handler = createHandler((_req, next) => next());
5854

59-
return handler(event, context, (err, res) => {
60-
if (err) return done(err);
61-
62-
expect(res).toEqual({
63-
statusCode: 404,
64-
body: "Cannot GET /test",
65-
multiValueHeaders: {
66-
"content-type": ["text/plain"],
67-
"content-security-policy": ["default-src 'self'"],
68-
"x-content-type-options": ["nosniff"],
69-
"content-length": ["16"]
70-
},
71-
isBase64Encoded: false
72-
});
73-
74-
return done();
55+
const res = await handler(event, context);
56+
57+
expect(res).toEqual({
58+
statusCode: 404,
59+
body: "Cannot GET /test",
60+
multiValueHeaders: {
61+
"content-type": ["text/plain"],
62+
"content-security-policy": ["default-src 'self'"],
63+
"x-content-type-options": ["nosniff"],
64+
"content-length": ["16"]
65+
},
66+
isBase64Encoded: false
7567
});
7668
});
7769

78-
it("should support multiple headers of the same key", done => {
70+
it("should support multiple headers of the same key", async () => {
7971
const handler = createHandler(() => {
8072
return new Response(null, {
8173
headers: {
@@ -84,37 +76,29 @@ describe("servie-lambda", () => {
8476
});
8577
});
8678

87-
return handler(event, context, (err, res) => {
88-
if (err) return done(err);
79+
const res = await handler(event, context);
8980

90-
expect(res).toEqual({
91-
statusCode: 200,
92-
body: "",
93-
multiValueHeaders: {
94-
"set-cookie": ["a=a", "b=b", "c=c"]
95-
},
96-
isBase64Encoded: false
97-
});
98-
99-
return done();
81+
expect(res).toEqual({
82+
statusCode: 200,
83+
body: "",
84+
multiValueHeaders: {
85+
"set-cookie": ["a=a", "b=b", "c=c"]
86+
},
87+
isBase64Encoded: false
10088
});
10189
});
10290

103-
it("should log and rewrite errors", done => {
91+
it("should log and rewrite errors", async () => {
10492
const logError = jest.fn();
10593
const handler = createHandler(() => Promise.reject(new Error("boom")), {
10694
logError
10795
});
10896

109-
return handler(event, context, (err, res) => {
110-
if (err) return done(err);
97+
const res = await handler(event, context);
11198

112-
expect(res!.statusCode).toEqual(500);
113-
expect(res!.isBase64Encoded).toEqual(false);
114-
expect(res!.body).toContain("boom");
115-
expect(logError).toHaveBeenCalled();
116-
117-
return done();
118-
});
99+
expect(res.statusCode).toEqual(500);
100+
expect(res.isBase64Encoded).toEqual(false);
101+
expect(res.body).toContain("boom");
102+
expect(logError).toHaveBeenCalled();
119103
});
120104
});

src/index.ts

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import { errorhandler } from "servie-errorhandler";
44
import { finalhandler } from "servie-finalhandler";
55
import {
66
APIGatewayEvent as Event,
7-
APIGatewayProxyHandler as Handler,
87
APIGatewayProxyResult as Result,
98
Context
109
} from "aws-lambda";
1110

12-
export { Handler, Event, Context, Result };
11+
export { Event, Context, Result };
12+
13+
/**
14+
* AWS Lambda promise handler.
15+
*/
16+
export type Handler = (event: Event, context: Context) => Promise<Result>;
1317

1418
/**
1519
* Extends `Request` with AWS lambda context.
@@ -54,7 +58,7 @@ export interface Options {
5458
* Create a server for handling AWS Lambda requests.
5559
*/
5660
export function createHandler(app: App, options: Options = {}): Handler {
57-
return function(event, context, callback): void {
61+
return function(event, context): Promise<Result> {
5862
const { httpMethod: method } = event;
5963
const url = format({
6064
pathname: event.path,
@@ -64,7 +68,6 @@ export function createHandler(app: App, options: Options = {}): Handler {
6468
const body = event.body
6569
? Buffer.from(event.body, event.isBase64Encoded ? "base64" : "utf8")
6670
: undefined;
67-
let didRespond = false;
6871

6972
const req = new LambdaRequest(url, {
7073
headers: event.multiValueHeaders,
@@ -79,9 +82,7 @@ export function createHandler(app: App, options: Options = {}): Handler {
7982
production: options.production
8083
});
8184

82-
function sendResponse(res: Response): Promise<void> {
83-
if (didRespond) return Promise.resolve();
84-
85+
function sendResponse(res: Response): Promise<Result> {
8586
req.signal.emit("responseStarted");
8687

8788
return res.buffer().then(
@@ -91,36 +92,41 @@ export function createHandler(app: App, options: Options = {}): Handler {
9192
const isBase64Encoded = isBinary(res);
9293
const body = buffer.toString(isBase64Encoded ? "base64" : "utf8");
9394

94-
didRespond = true;
95-
9695
// Emit stats at end of response.
9796
req.signal.emit("responseBytes", buffer ? buffer.byteLength : 0);
9897
req.signal.emit("responseEnded");
9998

100-
return callback(null, {
99+
return {
101100
statusCode,
102101
multiValueHeaders,
103102
body,
104103
isBase64Encoded
105-
});
104+
};
106105
},
107106
err => sendResponse(mapError(err))
108107
);
109108
}
110109

111-
req.signal.on("abort", () =>
112-
sendResponse(new Response(null, { status: 444 }))
113-
);
114-
115110
// Marked request as finished.
116111
req.signal.emit("requestStarted");
117112
req.signal.emit("requestBytes", body ? body.byteLength : 0);
118113
req.signal.emit("requestStarted");
119114

120-
Promise.resolve(app(req, finalhandler(req))).then(
121-
res => sendResponse(res),
122-
err => sendResponse(mapError(err))
123-
);
115+
return new Promise(resolve => {
116+
let result: Promise<Result> | undefined;
117+
118+
req.signal.on("abort", () => {
119+
result = sendResponse(new Response(null, { status: 444 }));
120+
return resolve(result);
121+
});
122+
123+
return resolve(
124+
Promise.resolve(app(req, finalhandler(req))).then(
125+
res => result || sendResponse(res),
126+
err => result || sendResponse(mapError(err))
127+
)
128+
);
129+
});
124130
};
125131
}
126132

0 commit comments

Comments
 (0)