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

fix: restored the compact layer #126

Merged
merged 2 commits into from
Nov 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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