Skip to content
This repository was archived by the owner on Jul 23, 2023. It is now read-only.

Commit 96d7923

Browse files
authored
fix: restored the compact layer (#126)
* fix: restored the compact layer * fix: linter issue
1 parent 328a548 commit 96d7923

File tree

3 files changed

+141
-8
lines changed

3 files changed

+141
-8
lines changed

src/compatLayer.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// @ts-nocheck
2+
/**
3+
* Credits to https://github.com/danielcondemarin
4+
* https://github.com/danielcondemarin/serverless-nextjs-plugin/blob/master/packages/next-aws-lambda/lib/compatLayer.js
5+
*/
6+
const Stream = require("stream");
7+
const queryString = require("querystring");
8+
9+
const requestResponseMapper = (event, callback) => {
10+
const base64Support = process.env.BINARY_SUPPORT === "yes";
11+
const response = {
12+
body: Buffer.from(""),
13+
isBase64Encoded: base64Support,
14+
statusCode: 200,
15+
multiValueHeaders: {}
16+
};
17+
18+
const request = new Stream.Readable();
19+
request.url = (event.requestContext.path || event.path || "").replace(new RegExp("^/" + event.requestContext.stage), "");
20+
21+
let qs = "";
22+
23+
if (event.multiValueQueryStringParameters) {
24+
qs += queryString.stringify(event.multiValueQueryStringParameters);
25+
}
26+
27+
if (event.pathParameters) {
28+
const pathParametersQs = queryString.stringify(event.pathParameters);
29+
30+
if (qs.length > 0) {
31+
qs += `&${pathParametersQs}`;
32+
} else {
33+
qs += pathParametersQs;
34+
}
35+
}
36+
37+
const hasQueryString = qs.length > 0;
38+
39+
if (hasQueryString) {
40+
request.url += `?${qs}`;
41+
}
42+
43+
request.method = event.httpMethod;
44+
request.rawHeaders = [];
45+
request.headers = {};
46+
47+
const headers = event.multiValueHeaders || {};
48+
49+
for (const key of Object.keys(headers)) {
50+
for (const value of headers[key]) {
51+
request.rawHeaders.push(key);
52+
request.rawHeaders.push(value);
53+
}
54+
request.headers[key.toLowerCase()] = headers[key].toString();
55+
}
56+
57+
request.getHeader = name => {
58+
return request.headers[name.toLowerCase()];
59+
};
60+
request.getHeaders = () => {
61+
return request.headers;
62+
};
63+
64+
request.connection = {};
65+
66+
// eslint-disable-next-line unicorn/prevent-abbreviations
67+
const res = new Stream();
68+
Object.defineProperty(res, "statusCode", {
69+
get() {
70+
return response.statusCode;
71+
},
72+
set(statusCode) {
73+
response.statusCode = statusCode;
74+
}
75+
});
76+
res.headers = {};
77+
res.writeHead = (status, headers) => {
78+
response.statusCode = status;
79+
if (headers) res.headers = Object.assign(res.headers, headers);
80+
};
81+
res.write = chunk => {
82+
response.body = Buffer.concat([response.body, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)]);
83+
};
84+
res.setHeader = (name, value) => {
85+
res.headers[name] = value;
86+
};
87+
res.removeHeader = name => {
88+
delete res.headers[name];
89+
};
90+
res.getHeader = name => {
91+
return res.headers[name.toLowerCase()];
92+
};
93+
res.getHeaders = () => {
94+
return res.headers;
95+
};
96+
res.end = text => {
97+
if (text) res.write(text);
98+
response.body = Buffer.from(response.body).toString(base64Support ? "base64" : undefined);
99+
response.multiValueHeaders = res.headers;
100+
res.writeHead(response.statusCode);
101+
fixApiGatewayMultipleHeaders();
102+
callback(null, response);
103+
};
104+
if (event.body) {
105+
request.push(event.body, event.isBase64Encoded ? "base64" : undefined);
106+
request.push(null);
107+
}
108+
109+
// eslint-disable-next-line unicorn/consistent-function-scoping
110+
function fixApiGatewayMultipleHeaders() {
111+
for (const key of Object.keys(response.multiValueHeaders)) {
112+
if (!Array.isArray(response.multiValueHeaders[key])) {
113+
response.multiValueHeaders[key] = [response.multiValueHeaders[key]];
114+
}
115+
}
116+
}
117+
118+
// eslint-disable-next-line unicorn/prevent-abbreviations
119+
return { req: request, res };
120+
};
121+
122+
module.exports = requestResponseMapper;

src/constants.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const path = require("path");
2+
13
const PROVIDERS = {
24
AWS: "AWS"
35
};
@@ -8,9 +10,11 @@ const FILE_NAMES = {
810
};
911

1012
const NEXT_CONFIG = "next.config.js";
13+
const COMPAT_LAYER_PATH = path.resolve(__dirname);
1114

1215
module.exports = {
1316
PROVIDERS,
1417
FILE_NAMES,
15-
NEXT_CONFIG
18+
NEXT_CONFIG,
19+
COMPAT_LAYER_PATH
1620
};

src/providers/aws/generateLambdas.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ const path = require("path");
33
const { generateLambdaResource } = require("./resources/terraFormLambda");
44
const { generateZipResource } = require("./resources/terraFormZip.js");
55
const { getBuildPath, getServerlessBuildPath } = require("../../configuration");
6-
const { FILE_NAMES } = require("../../constants");
6+
const { COMPAT_LAYER_PATH, FILE_NAMES } = require("../../constants");
77
const { getLambdaFiles } = require("../../shared");
88
const FolderNotFoundError = require("../../errors/folderNotFoundError");
99

1010
function generateLambda(filename, thePath) {
1111
const lambdaTemplate = `
1212
13+
const compatLayer = require('./compatLayer.js');
1314
const page = require('./${filename}.original.js');
14-
const http = require('http')
1515
1616
exports.render = (event, context, callback) => {
17-
const server = new http.Server((req, res) => page.render(req, res));
18-
server.listen(3000);
17+
const { req, res } = compatLayer(event, callback);
18+
page.render(req, res);
1919
};
2020
2121
@@ -63,8 +63,9 @@ function generateLambdas(write = false) {
6363
* 1. create a folder with name of the file
6464
* 2. copy the next file with a suffix .original.js
6565
* 3. create the lambda from the template
66-
* 4. generate the lambda resource
67-
* 5. generate the zip file resource
66+
* 4. copy the compact layer
67+
* 5. generate the lambda resource
68+
* 6. generate the zip file resource
6869
*/
6970
// 1.
7071
const lambdaName = file.replace(".js", "");
@@ -78,11 +79,17 @@ function generateLambdas(write = false) {
7879
generateLambda(lambdaName, buildPath);
7980

8081
// 4.
82+
fs.copyFileSync(
83+
path.resolve(COMPAT_LAYER_PATH, "./compatLayer.js"),
84+
path.resolve(buildPath, "lambdas", lambdaName, "compatLayer.js")
85+
);
86+
87+
// 5.
8188
const lambdaResource = generateLambdaResource({ id: lambdaName });
8289
lambdasResources[lambdaResource.resourceUniqueId] = lambdaResource.resource;
8390
lambdasPermissions[lambdaResource.permissionUniqueId] = lambdaResource.permission;
8491

85-
// 5.
92+
// 6.
8693
const zipResource = generateZipResource({
8794
id: lambdaName,
8895
directoryName: lambdaName

0 commit comments

Comments
 (0)