UNPKG

@codification/cutwater-aws

Version:

A library providing general functionality for TypeScript based AWS projects.

199 lines 8.48 kB
"use strict"; 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