@codification/cutwater-aws
Version:
A library providing general functionality for TypeScript based AWS projects.
199 lines • 8.48 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.LambdaEdgeUtils = void 0;
const cutwater_node_core_1 = require("@codification/cutwater-node-core");
const BLACK_LISTED_HEADERS = [
'Connection',
'Expect',
'Keep-alive',
'Proxy-Authenticate',
'Proxy-Authorization',
'Proxy-Connection',
'Trailer',
'Upgrade',
'X-Accel-Buffering',
'X-Accel-Charset',
'X-Accel-Limit-Rate',
'X-Accel-Redirect',
'X-Cache',
'X-Forwarded-Proto',
'X-Real-IP',
].map((header) => header.toLowerCase());
const READ_ONLY_HEADERS_VIEWER_REQUEST = ['Content-Length', 'Host', 'Transfer-Encoding', 'Via'].map((header) => header.toLowerCase());
const READ_ONLY_HEADERS_ORIGIN_REQUEST = [
'Accept-Encoding',
'Content-Length',
'If-Modified-Since',
'If-None-Match',
'If-Range',
'If-Unmodified-Since',
'Range',
'Transfer-Encoding',
'Via',
].map((header) => header.toLowerCase());
const READ_ONLY_HEADERS_ORIGIN_RESPONSE = ['Transfer-Encoding', 'Via'].map((header) => header.toLowerCase());
const READ_ONLY_HEADERS_VIEWER_RESPONSE = [
'Content-Encoding',
'Content-Length',
'Transfer-Encoding',
'Warning',
'Via',
].map((header) => header.toLowerCase());
/**
* @beta
*/
class LambdaEdgeUtils {
/**
* Returns a new `CloudFrontHeaders` object with the specified `headerList` removed.
*
* This method also removes all headers that are black listed, as found
* [here]{@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-header-restrictions}.
*
* @param headers - the `CloudFrontHeaders` to be filtered
* @param headerList - names of the headers to be removed
* @returns a new filtered `CloudFrontHeaders` object
*/
static stripHeaders(headers, headerList) {
const rval = {};
const fullHeaderList = [];
fullHeaderList.push(...headerList, ...BLACK_LISTED_HEADERS);
Object.keys(headers)
.filter((headerName) => fullHeaderList.indexOf(headerName) === -1)
.forEach((headerName) => {
rval[headerName] = headers[headerName];
});
return rval;
}
/**
* Returns a new `CloudFrontHeaders` object with the read-only viewer request headers
* (as specified [here]{@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-header-restrictions})
* removed.
*
* This method also removes all headers that are black listed, as found
* [here]{@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-header-restrictions}.
*
* @param headers - the `CloudFrontHeaders` to be filtered
* @returns a new filtered `CloudFrontHeaders` object
*/
static stripViewerRequestHeaders(headers) {
return LambdaEdgeUtils.stripHeaders(headers, READ_ONLY_HEADERS_VIEWER_REQUEST);
}
/**
* Returns a new `CloudFrontHeaders` object with the read-only origin request headers
* (as specified [here]{@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-header-restrictions})
* removed.
*
* This method also removes all headers that are black listed, as found
* [here]{@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-header-restrictions}.
*
* @param headers - the `CloudFrontHeaders` to be filtered
* @returns a new filtered `CloudFrontHeaders` object
*/
static stripOriginRequestHeaders(headers) {
return LambdaEdgeUtils.stripHeaders(headers, READ_ONLY_HEADERS_ORIGIN_REQUEST);
}
/**
* Returns a new `CloudFrontHeaders` object with the read-only viewer response headers
* (as specified [here]{@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-header-restrictions})
* removed.
*
* This method also removes all headers that are black listed, as found
* [here]{@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-header-restrictions}.
*
* @param headers - the `CloudFrontHeaders` to be filtered
* @returns a new filtered `CloudFrontHeaders` object
*/
static stripViewerResponseHeaders(headers) {
return LambdaEdgeUtils.stripHeaders(headers, READ_ONLY_HEADERS_VIEWER_RESPONSE);
}
/**
* Returns a new `CloudFrontHeaders` object with the read-only origin response headers
* (as specified [here]{@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-header-restrictions})
* removed.
*
* This method also removes all headers that are black listed, as found
* [here]{@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-header-restrictions}.
*
* @param headers - the `CloudFrontHeaders` to be filtered
* @returns a new filtered `CloudFrontHeaders` object
*/
static stripOriginResponseHeaders(headers) {
return LambdaEdgeUtils.stripHeaders(headers, READ_ONLY_HEADERS_ORIGIN_RESPONSE);
}
/**
* Converts `CloudFrontHeaders` to `IncomingHttpHeaders` provided by node.
*
* @param headers - the headers from CloudFront to be converted
* @returns the converted headers
*/
static toCloudFrontHeaders(headers) {
const rval = {};
let value;
Object.keys(headers).forEach((headerName) => {
value = headers[headerName];
if (typeof value === 'string') {
value = [value];
}
if (typeof value !== 'undefined') {
rval[headerName.toLowerCase()] = value.map((headerValue) => ({ key: headerName, value: headerValue }));
}
});
return rval;
}
/**
* Converts an origin's response (`IncomingMessage`) to a response that can be returned to a CloudFront viewer.
*
* @param originResponse - the response recieved from the origin
* @returns a response to be returned to a CloudFront viewer
*/
static originResponseToCloudFrontResultResponse(originResponse) {
const rval = {};
rval.status = (originResponse.statusCode ? originResponse.statusCode : 500).toString();
rval.statusDescription = originResponse.statusMessage;
rval.headers = LambdaEdgeUtils.stripOriginRequestHeaders(LambdaEdgeUtils.toCloudFrontHeaders(originResponse.headers));
if (cutwater_node_core_1.HttpUtils.isResponseOk(originResponse)) {
return new Promise((resolve, reject) => {
cutwater_node_core_1.HttpUtils.toBodyText(originResponse)
.then((bodyText) => {
rval.bodyEncoding = 'text';
rval.body = bodyText;
resolve(rval);
})
.catch((reason) => reject(reason));
});
}
else {
return Promise.resolve(rval);
}
}
static toCloudFrontCustomOrigin(request) {
if (request && request.origin && request.origin.custom) {
return request.origin.custom;
}
else {
throw new Error('Request does not contain a custom origin.');
}
}
static isCustomOriginRequestEvent(event) {
const { config, request } = event.Records[0].cf;
return config.eventType === 'origin-request' && LambdaEdgeUtils.toCloudFrontCustomOrigin(request) ? true : false;
}
static isCustomOriginResponseEvent(event) {
const { config } = event.Records[0].cf;
return config.eventType === 'origin-response';
}
static toIncomingHttpHeaders(headers) {
const rval = {};
if (headers) {
Object.keys(headers).forEach((name) => {
const header = headers[name];
if (header && header.length > 0 && header[0].key) {
rval[header[0].key] = header.length > 1 ? header.map((obj) => obj.value) : header[0].value;
}
});
}
return rval;
}
}
exports.LambdaEdgeUtils = LambdaEdgeUtils;
//# sourceMappingURL=LambdaEdgeUtils.js.map