cassava
Version:
AWS API Gateway Router
113 lines • 4.97 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProxyRoute = void 0;
const http = require("http");
const https = require("https");
const querystring = require("querystring");
const url = require("url");
/**
* Proxies requests to another server.
*/
class ProxyRoute {
constructor(config) {
this.config = config;
if (!config) {
throw new Error("config must be set");
}
if (typeof config.srcPath !== "string") {
throw new Error("config.srcPath must be set");
}
if (!config.srcPath.startsWith("/")) {
throw new Error("config.srcPath must start with `/`");
}
if (config.srcPath.includes("?") || config.srcPath.includes("#")) {
throw new Error("config.srcPath cannot define a query or hash");
}
if (typeof config.destPath !== "string") {
throw new Error("config.destPath must be set");
}
if (!config.destPath.match(/^https?:\/\//)) {
throw new Error("config.destPath must start with http:// or https://");
}
if (config.destPath.includes("?") || config.destPath.includes("#")) {
throw new Error("config.destPath cannot define a query or hash");
}
this.parsedDest = url.parse ? url.parse(config.destPath) : new url.URL(config.destPath);
}
matches(evt) {
return evt.path.startsWith(this.config.srcPath) && (evt.path.length === this.config.srcPath.length || this.config.srcPath.endsWith("/") || evt.path[this.config.srcPath.length] === "/");
}
handle(evt) {
return __awaiter(this, void 0, void 0, function* () {
let reqArgs = {
protocol: this.parsedDest.protocol,
hostname: this.parsedDest.hostname,
method: evt.httpMethod,
headers: Object.assign(Object.assign({}, evt.headers), this.config.additionalHeaders),
path: this.parsedDest.path + evt.path.substr(this.config.srcPath.length)
};
if (evt.multiValueQueryStringParameters) {
const q = querystring.stringify(evt.multiValueQueryStringParameters);
if (q.length) {
reqArgs.path += "?" + q;
}
}
if (this.config.requestMapper) {
reqArgs = yield this.config.requestMapper(reqArgs);
if (!reqArgs) {
return null;
}
}
let body = evt.body;
if (body && this.config.bodyMapper) {
body = yield this.config.bodyMapper(body);
}
let bodyContentType = body && this.getRequestBodyContentType(reqArgs);
if (body && !bodyContentType) {
bodyContentType = reqArgs.headers["Content-Type"] = "application/json";
}
// Do this manually so as to not create another dependency.
return new Promise((resolve, reject) => {
const reqFunction = reqArgs.protocol === "http:" ? http.request : https.request;
const req = reqFunction(reqArgs, res => {
const response = {
statusCode: res.statusCode,
headers: res.headers,
body: ""
};
res.on("data", d => response.body += d);
res.on("end", () => resolve(response));
});
req.on("error", e => reject(e));
if (body !== undefined) {
if (typeof body === "string" && !bodyContentType.match(/json$/)) {
req.write(body);
}
else {
req.write(JSON.stringify(body));
}
}
req.end();
});
});
}
getRequestBodyContentType(reqArgs) {
for (const header of Object.keys(reqArgs.headers)) {
if (header.toLowerCase() === "content-type") {
return reqArgs.headers[header];
}
}
return null;
}
}
exports.ProxyRoute = ProxyRoute;
//# sourceMappingURL=ProxyRoute.js.map