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

Commit

Permalink
fix: restored the compact layer (#126)
Browse files Browse the repository at this point in the history
* fix: restored the compact layer

* fix: linter issue
  • Loading branch information
ematipico authored Nov 13, 2019
1 parent 328a548 commit 96d7923
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 8 deletions.
122 changes: 122 additions & 0 deletions src/compatLayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// @ts-nocheck
/**
* Credits to https://github.com/danielcondemarin
* https://github.com/danielcondemarin/serverless-nextjs-plugin/blob/master/packages/next-aws-lambda/lib/compatLayer.js
*/
const Stream = require("stream");
const queryString = require("querystring");

const requestResponseMapper = (event, callback) => {
const base64Support = process.env.BINARY_SUPPORT === "yes";
const response = {
body: Buffer.from(""),
isBase64Encoded: base64Support,
statusCode: 200,
multiValueHeaders: {}
};

const request = new Stream.Readable();
request.url = (event.requestContext.path || event.path || "").replace(new RegExp("^/" + event.requestContext.stage), "");

let qs = "";

if (event.multiValueQueryStringParameters) {
qs += queryString.stringify(event.multiValueQueryStringParameters);
}

if (event.pathParameters) {
const pathParametersQs = queryString.stringify(event.pathParameters);

if (qs.length > 0) {
qs += `&${pathParametersQs}`;
} else {
qs += pathParametersQs;
}
}

const hasQueryString = qs.length > 0;

if (hasQueryString) {
request.url += `?${qs}`;
}

request.method = event.httpMethod;
request.rawHeaders = [];
request.headers = {};

const headers = event.multiValueHeaders || {};

for (const key of Object.keys(headers)) {
for (const value of headers[key]) {
request.rawHeaders.push(key);
request.rawHeaders.push(value);
}
request.headers[key.toLowerCase()] = headers[key].toString();
}

request.getHeader = name => {
return request.headers[name.toLowerCase()];
};
request.getHeaders = () => {
return request.headers;
};

request.connection = {};

// eslint-disable-next-line unicorn/prevent-abbreviations
const res = new Stream();
Object.defineProperty(res, "statusCode", {
get() {
return response.statusCode;
},
set(statusCode) {
response.statusCode = statusCode;
}
});
res.headers = {};
res.writeHead = (status, headers) => {
response.statusCode = status;
if (headers) res.headers = Object.assign(res.headers, headers);
};
res.write = chunk => {
response.body = Buffer.concat([response.body, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)]);
};
res.setHeader = (name, value) => {
res.headers[name] = value;
};
res.removeHeader = name => {
delete res.headers[name];
};
res.getHeader = name => {
return res.headers[name.toLowerCase()];
};
res.getHeaders = () => {
return res.headers;
};
res.end = text => {
if (text) res.write(text);
response.body = Buffer.from(response.body).toString(base64Support ? "base64" : undefined);
response.multiValueHeaders = res.headers;
res.writeHead(response.statusCode);
fixApiGatewayMultipleHeaders();
callback(null, response);
};
if (event.body) {
request.push(event.body, event.isBase64Encoded ? "base64" : undefined);
request.push(null);
}

// eslint-disable-next-line unicorn/consistent-function-scoping
function fixApiGatewayMultipleHeaders() {
for (const key of Object.keys(response.multiValueHeaders)) {
if (!Array.isArray(response.multiValueHeaders[key])) {
response.multiValueHeaders[key] = [response.multiValueHeaders[key]];
}
}
}

// eslint-disable-next-line unicorn/prevent-abbreviations
return { req: request, res };
};

module.exports = requestResponseMapper;
6 changes: 5 additions & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const path = require("path");

const PROVIDERS = {
AWS: "AWS"
};
Expand All @@ -8,9 +10,11 @@ const FILE_NAMES = {
};

const NEXT_CONFIG = "next.config.js";
const COMPAT_LAYER_PATH = path.resolve(__dirname);

module.exports = {
PROVIDERS,
FILE_NAMES,
NEXT_CONFIG
NEXT_CONFIG,
COMPAT_LAYER_PATH
};
21 changes: 14 additions & 7 deletions src/providers/aws/generateLambdas.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ const path = require("path");
const { generateLambdaResource } = require("./resources/terraFormLambda");
const { generateZipResource } = require("./resources/terraFormZip.js");
const { getBuildPath, getServerlessBuildPath } = require("../../configuration");
const { FILE_NAMES } = require("../../constants");
const { COMPAT_LAYER_PATH, FILE_NAMES } = require("../../constants");
const { getLambdaFiles } = require("../../shared");
const FolderNotFoundError = require("../../errors/folderNotFoundError");

function generateLambda(filename, thePath) {
const lambdaTemplate = `
const compatLayer = require('./compatLayer.js');
const page = require('./${filename}.original.js');
const http = require('http')
exports.render = (event, context, callback) => {
const server = new http.Server((req, res) => page.render(req, res));
server.listen(3000);
const { req, res } = compatLayer(event, callback);
page.render(req, res);
};
Expand Down Expand Up @@ -63,8 +63,9 @@ function generateLambdas(write = false) {
* 1. create a folder with name of the file
* 2. copy the next file with a suffix .original.js
* 3. create the lambda from the template
* 4. generate the lambda resource
* 5. generate the zip file resource
* 4. copy the compact layer
* 5. generate the lambda resource
* 6. generate the zip file resource
*/
// 1.
const lambdaName = file.replace(".js", "");
Expand All @@ -78,11 +79,17 @@ function generateLambdas(write = false) {
generateLambda(lambdaName, buildPath);

// 4.
fs.copyFileSync(
path.resolve(COMPAT_LAYER_PATH, "./compatLayer.js"),
path.resolve(buildPath, "lambdas", lambdaName, "compatLayer.js")
);

// 5.
const lambdaResource = generateLambdaResource({ id: lambdaName });
lambdasResources[lambdaResource.resourceUniqueId] = lambdaResource.resource;
lambdasPermissions[lambdaResource.permissionUniqueId] = lambdaResource.permission;

// 5.
// 6.
const zipResource = generateZipResource({
id: lambdaName,
directoryName: lambdaName
Expand Down

0 comments on commit 96d7923

Please sign in to comment.