From 9b2e9db22bef099891da3b869525cbbfd53ddf4b Mon Sep 17 00:00:00 2001 From: Krishan Thisera Date: Thu, 2 Feb 2023 13:37:02 +1030 Subject: [PATCH] DO-1438: Use middified handlers with the prerender proxy --- .../lib/handlers/cache-control.ts | 27 ++------ .../lib/handlers/error-response.ts | 59 +++------------- .../lib/handlers/package-lock.json | 68 +++++++++++++++++-- .../prerender-proxy/lib/handlers/package.json | 7 +- .../lib/handlers/prerender-check.ts | 35 +++------- .../prerender-proxy/lib/handlers/prerender.ts | 51 +++----------- 6 files changed, 99 insertions(+), 148 deletions(-) diff --git a/packages/prerender-proxy/lib/handlers/cache-control.ts b/packages/prerender-proxy/lib/handlers/cache-control.ts index cb15455f..4951bbd2 100644 --- a/packages/prerender-proxy/lib/handlers/cache-control.ts +++ b/packages/prerender-proxy/lib/handlers/cache-control.ts @@ -1,21 +1,8 @@ -import 'source-map-support/register'; -import { CloudFrontResponseEvent, CloudFrontResponse } from 'aws-lambda'; -/* - Prerender cache control function - Consider associate this function as *origin response* function -*/ -export const handler = async (event: CloudFrontResponseEvent): Promise => { - const cacheKey = process.env.PRERENDER_CACHE_KEY || 'x-prerender-requestid'; - const cacheMaxAge = process.env.PRERENDER_CACHE_MAX_AGE || '0'; - let response = event.Records[0].cf.response; +import middy from "@middy/core"; +import { PrerenderCacheControlHandler } from "@aligent/cdk-lambda-at-edge-handlers"; - if (response.headers[`${cacheKey}`]) { - response.headers['Cache-Control'] = [ - { - key: 'Cache-Control', - value: `max-age=${cacheMaxAge}` - } - ] - } - return response; -} +/** + * Prerender Cache Control Handler + * @link https://github.com/aligent/cdk-constructs/blob/main/packages/lambda-at-edge-handlers/lib/cache-control.ts + */ +export const handler = middy(PrerenderCacheControlHandler); \ No newline at end of file diff --git a/packages/prerender-proxy/lib/handlers/error-response.ts b/packages/prerender-proxy/lib/handlers/error-response.ts index 15bacb6a..4563cc3c 100644 --- a/packages/prerender-proxy/lib/handlers/error-response.ts +++ b/packages/prerender-proxy/lib/handlers/error-response.ts @@ -1,51 +1,8 @@ -import 'source-map-support/register'; -import { CloudFrontRequest, CloudFrontResponseEvent, CloudFrontResponse } from 'aws-lambda'; -import axios from "axios"; -import { URL } from 'url'; -import * as https from 'https'; - -const FRONTEND_HOST = process.env.FRONTEND_HOST; -const PATH_PREFIX = process.env.PATH_PREFIX; - -// Create axios client outside of lambda function for re-use between calls -const instance = axios.create({ - timeout: 1000, - // Don't follow redirects - maxRedirects: 0, - // Only valid response codes are 200 - validateStatus: function (status) { - return status == 200; - }, - // keep connection alive so we don't constantly do SSL negotiation - httpsAgent: new https.Agent({ keepAlive: true }), -}); - -export const handler = (event: CloudFrontResponseEvent): Promise => { - let response = event.Records[0].cf.response; - let request = event.Records[0].cf.request; - - if (response.status != '200' && - ! request.headers['x-request-prerender'] && - request.uri != `${PATH_PREFIX}/index.html`) { - - // Fetch default page and return body - return instance.get(`https://${FRONTEND_HOST}${PATH_PREFIX}/index.html`).then((res) => { - response.body = res.data; - - - response.headers['content-type'] = [{ - key: 'Content-Type', - value: 'text/html' - }]; - - // Remove content-length if set as this may be the value from the origin. - delete response.headers['content-length'] - - return response; - }).catch((err) => { - return response - }); - } - - return Promise.resolve(response); -} +import middy from "@middy/core"; +import { PrerenderErrorResponseHandler } from "@aligent/cdk-lambda-at-edge-handlers"; + +/** + * Prerender Error ResponseHandler + * @link https://github.com/aligent/cdk-constructs/blob/main/packages/lambda-at-edge-handlers/lib/error-response.ts + */ +export const handler = middy(PrerenderErrorResponseHandler); \ No newline at end of file diff --git a/packages/prerender-proxy/lib/handlers/package-lock.json b/packages/prerender-proxy/lib/handlers/package-lock.json index 714febac..66dd2b1d 100644 --- a/packages/prerender-proxy/lib/handlers/package-lock.json +++ b/packages/prerender-proxy/lib/handlers/package-lock.json @@ -6,10 +6,34 @@ "": { "license": "ISC", "dependencies": { + "@aligent/cdk-lambda-at-edge-handlers": "^0.1.0", + "@middy/core": "^3.6.2", "@types/aws-lambda": "^8.10.77", "@types/node": "^15.12.4", "axios": "^0.21.1", "source-map-support": "^0.5.19" + }, + "devDependencies": { + "@types/node": "^18.11.9" + } + }, + "node_modules/@aligent/cdk-lambda-at-edge-handlers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@aligent/cdk-lambda-at-edge-handlers/-/cdk-lambda-at-edge-handlers-0.1.0.tgz", + "integrity": "sha512-5qZi5NWXDySDr6Djv+EuA4Y1+f3imQSkSI9sBFzizG/cqfTb5dHF96n3GERpwvNbo4xIuIB7GRLQ4xh3U9PcUA==", + "dependencies": { + "@types/aws-lambda": "^8.10.77", + "axios": "^0.21.1", + "esbuild": "0.12.15", + "source-map-support": "^0.5.16" + } + }, + "node_modules/@middy/core": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@middy/core/-/core-3.6.2.tgz", + "integrity": "sha512-/vyvG34RIt7CTmuB/jksGkk9vs6RCoOlRFPfdQq11dHkiKlT2mm8j/jZx7gSpEhXXh9LeaEMuKPnsgWBIlGS1g==", + "engines": { + "node": ">=14" } }, "node_modules/@types/aws-lambda": { @@ -18,9 +42,10 @@ "integrity": "sha512-n0EMFJU/7u3KvHrR83l/zrKOVURXl5pUJPNED/Bzjah89QKCHwCiKCBoVUXRwTGRfCYGIDdinJaAlKDHZdp/Ng==" }, "node_modules/@types/node": { - "version": "15.12.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.4.tgz", - "integrity": "sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==" + "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "dev": true }, "node_modules/axios": { "version": "0.21.1", @@ -35,6 +60,15 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, + "node_modules/esbuild": { + "version": "0.12.15", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.15.tgz", + "integrity": "sha512-72V4JNd2+48eOVCXx49xoSWHgC3/cCy96e7mbXKY+WOWghN00cCmlGnwVLRhRHorvv0dgCyuMYBZlM2xDM5OQw==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + } + }, "node_modules/follow-redirects": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", @@ -62,15 +96,32 @@ } }, "dependencies": { + "@aligent/cdk-lambda-at-edge-handlers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@aligent/cdk-lambda-at-edge-handlers/-/cdk-lambda-at-edge-handlers-0.1.0.tgz", + "integrity": "sha512-5qZi5NWXDySDr6Djv+EuA4Y1+f3imQSkSI9sBFzizG/cqfTb5dHF96n3GERpwvNbo4xIuIB7GRLQ4xh3U9PcUA==", + "requires": { + "@types/aws-lambda": "^8.10.77", + "axios": "^0.21.1", + "esbuild": "0.12.15", + "source-map-support": "^0.5.16" + } + }, + "@middy/core": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@middy/core/-/core-3.6.2.tgz", + "integrity": "sha512-/vyvG34RIt7CTmuB/jksGkk9vs6RCoOlRFPfdQq11dHkiKlT2mm8j/jZx7gSpEhXXh9LeaEMuKPnsgWBIlGS1g==" + }, "@types/aws-lambda": { "version": "8.10.77", "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.77.tgz", "integrity": "sha512-n0EMFJU/7u3KvHrR83l/zrKOVURXl5pUJPNED/Bzjah89QKCHwCiKCBoVUXRwTGRfCYGIDdinJaAlKDHZdp/Ng==" }, "@types/node": { - "version": "15.12.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.4.tgz", - "integrity": "sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==" + "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "dev": true }, "axios": { "version": "0.21.1", @@ -85,6 +136,11 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, + "esbuild": { + "version": "0.12.15", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.15.tgz", + "integrity": "sha512-72V4JNd2+48eOVCXx49xoSWHgC3/cCy96e7mbXKY+WOWghN00cCmlGnwVLRhRHorvv0dgCyuMYBZlM2xDM5OQw==" + }, "follow-redirects": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", diff --git a/packages/prerender-proxy/lib/handlers/package.json b/packages/prerender-proxy/lib/handlers/package.json index e26bdaf0..1d4595b3 100644 --- a/packages/prerender-proxy/lib/handlers/package.json +++ b/packages/prerender-proxy/lib/handlers/package.json @@ -8,6 +8,11 @@ "@types/aws-lambda": "^8.10.77", "@types/node": "^15.12.4", "axios": "^0.21.1", - "source-map-support": "^0.5.19" + "source-map-support": "^0.5.19", + "@middy/core": "^3.6.2", + "@aligent/cdk-lambda-at-edge-handlers": "^0.1.0" + }, + "devDependencies": { + "@types/node": "^18.11.9" } } diff --git a/packages/prerender-proxy/lib/handlers/prerender-check.ts b/packages/prerender-proxy/lib/handlers/prerender-check.ts index 587230db..5de7f463 100644 --- a/packages/prerender-proxy/lib/handlers/prerender-check.ts +++ b/packages/prerender-proxy/lib/handlers/prerender-check.ts @@ -1,27 +1,8 @@ -import 'source-map-support/register'; -import { CloudFrontRequest, CloudFrontRequestEvent } from 'aws-lambda'; - -const IS_BOT = /googlebot|chrome-lighthouse|lighthouse|adsbot\-google|Feedfetcher\-Google|bingbot|yandex|baiduspider|Facebot|facebookexternalhit|twitterbot|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator/i; -const IS_FILE = /\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff|svg|eot)$/i; - -export const handler = async (event: CloudFrontRequestEvent): Promise => { - let request = event.Records[0].cf.request; - - // If the request is from a bot, is not a file and is not from prerender - // then set the x-request-prerender header so the origin-request lambda function - // alters the origin to prerender.io - if (!IS_FILE.test(request.uri) - && IS_BOT.test(request.headers['user-agent'][0].value) - && !request.headers['x-prerender']) { - request.headers['x-request-prerender'] = [ - { - key: 'x-request-prerender', - value: 'true' - } - ]; - - request.headers['x-prerender-host'] = [{ key: 'X-Prerender-Host', value: request.headers.host[0].value}]; - } - - return request; -} +import middy from "@middy/core"; +import { PrerenderCheckHandler } from "@aligent/cdk-lambda-at-edge-handlers"; + +/** + * Prerender Check Handler + * @link https://github.com/aligent/cdk-constructs/blob/main/packages/lambda-at-edge-handlers/lib/prerender-check.ts + */ +export const handler = middy(PrerenderCheckHandler); \ No newline at end of file diff --git a/packages/prerender-proxy/lib/handlers/prerender.ts b/packages/prerender-proxy/lib/handlers/prerender.ts index e6e6bd6a..ead14b2c 100644 --- a/packages/prerender-proxy/lib/handlers/prerender.ts +++ b/packages/prerender-proxy/lib/handlers/prerender.ts @@ -1,43 +1,8 @@ -import 'source-map-support/register'; -import { CloudFrontRequest, CloudFrontRequestEvent, CloudFrontResponse } from '@aws-cdk/aws-lambda'; - -const PRERENDER_TOKEN = process.env.PRERENDER_TOKEN; -const PATH_PREFIX = process.env.PATH_PREFIX; -const PRERENDER_URL = process.env.PRERENDER_URL; - -export const handler = async (event: CloudFrontRequestEvent): Promise => { - let request = event.Records[0].cf.request; - - // viewer-request function will determine whether we prerender or not - // if we should we add prerender as our custom origin - if (request.headers['x-request-prerender']) { - // Cloudfront will alter the request for / to /index.html - // since it is defined as the default root object - // we do not want to do this when prerendering the homepage - if (request.uri === `${PATH_PREFIX}/index.html`) { - request.uri = `${PATH_PREFIX}/`; - } - - request.origin = { - custom: { - domainName: PRERENDER_URL, - port: 443, - protocol: 'https', - readTimeout: 20, - keepaliveTimeout: 5, - sslProtocols: ['TLSv1', 'TLSv1.1', 'TLSv1.2'], - path: '/https%3A%2F%2F' + request.headers['x-prerender-host'][0].value, - customHeaders: { - 'x-prerender-token': [{ - key: 'x-prerender-token', - value: PRERENDER_TOKEN - }] - } - } - }; - } else { - request.uri = `${PATH_PREFIX}/index.html`; - } - - return request; -} +import middy from "@middy/core"; +import { PrerenderHandler } from "@aligent/cdk-lambda-at-edge-handlers"; + +/** + * Prerender Handler + * @link https://github.com/aligent/cdk-constructs/blob/main/packages/lambda-at-edge-handlers/lib/prerender.ts + */ +export const handler = middy(PrerenderHandler); \ No newline at end of file