Skip to content

Instantly share code, notes, and snippets.

@awestover89
Last active April 23, 2018 06:57
Show Gist options
  • Save awestover89/a53c0f2811c566c902a473ea22e825a5 to your computer and use it in GitHub Desktop.
Save awestover89/a53c0f2811c566c902a473ea22e825a5 to your computer and use it in GitHub Desktop.
Node.js lambda function for gw_proxy
var http = require('http');
var https = require('https');
var util = require('util');
exports.handler = function(event, context, callback) {
console.log(util.inspect(event, 3));
console.log(util.inspect(context, 3));
// setup request options and parameters
var options = {
host: event.requestParams.hostname,
port: event.requestParams.port,
path: event.requestParams.path,
method: event.requestParams.method
};
// if you have headers set them otherwise set the property to an empty map
if (event.params && event.params.header && Object.keys(event.params.header).length > 0) {
options.headers = event.params.header
} else {
options.headers = {};
}
// Grab the correct "Host" header
options.headers["Host"] = event.requestParams.hostname;
// Force the user agent and the "forwaded for" headers because we want to
// take them from the API Gateway context rather than letting Node.js set the Lambda ones
options.headers["User-Agent"] = event.context["user-agent"];
options.headers["X-Forwarded-For"] = event.context["source-ip"];
options.headers["X-dt-account-id"] = event.context["x-dt-account-id"];
// if I don't have a content type I force it application/json
// Test invoke in the API Gateway console does not pass a value
if (!options.headers["Content-Type"]) {
options.headers["Content-Type"] = "application/json";
}
// modify the path if necessary
if (event.params && event.params.path && Object.keys(event.params.path).length > 0) {
var updatedPath = replacePathParams(event.params.path, event.requestParams.path);
options.path = updatedPath;
}
// build the query string
if (event.params && event.params.querystring && Object.keys(event.params.querystring).length > 0) {
var queryString = generateQueryString(event.params.querystring);
if (queryString !== "") {
options.path += "?" + queryString;
}
}
// Define my callback to read the response and generate a JSON output for API Gateway.
// The JSON output is parsed by the mapping templates
callback = function(response) {
var responseString = '';
// Another chunk of data has been recieved, so append it to `str`
response.on('data', function (chunk) {
responseString += chunk;
});
// The whole response has been received
response.on('end', function () {
console.log(responseString);
// Parse response to json
var jsonResponse = JSON.parse(responseString);
var output = {
status: response.statusCode,
bodyJson: jsonResponse,
headers: response.headers
};
// if the response was a 200 we can just pass the entire JSON back to
// API Gateway for parsing. If the backend returned a non 200 status
// then we return it as an error
if (response.statusCode == 200) {
context.succeed(output);
} else {
// set the output JSON as a string inside the body property
output.bodyJson = responseString;
// stringify the whole thing again so that we can read it with
// the $util.parseJson method in the mapping templates
context.fail(JSON.stringify(output));
}
});
}
var req;
if (event.requestParams.scheme == 'http') {
req = http.request(options, callback);
}
else {
req = https.request(options, callback);
}
if (event.bodyJson && event.bodyJson !== "") {
req.write(JSON.stringify(event.bodyJson));
}
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
context.fail(JSON.stringify({
status: 500,
bodyJson: JSON.stringify({ message: "Internal server error" })
}));
});
req.end();
}
function replacePathParams(pathParams, path) {
var updatedPath = path;
for(var p in pathParams) {
if (pathParams.hasOwnProperty(p)) {
console.log('Replacing {' + p + '} with ' + pathParams[p]);
updatedPath = updatedPath.replace('{' + p + '}', pathParams[p]);
}
}
return updatedPath;
}
function generateQueryString(params) {
var str = [];
for(var p in params) {
if (params.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(params[p]));
}
}
return str.join("&");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment