From 9e1e71d8a3412a2e37febabacb4b4a58df726ef0 Mon Sep 17 00:00:00 2001 From: Richard Walkden Date: Thu, 17 Jul 2025 12:26:51 +0100 Subject: [PATCH 1/2] add netacea unified handler example --- docs/netacea_unified_handler.md | 27 ++++++++++ package-lock.json | 8 +-- package.json | 2 +- src/NetaceaUnified.ts | 89 +++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 docs/netacea_unified_handler.md create mode 100644 src/NetaceaUnified.ts diff --git a/docs/netacea_unified_handler.md b/docs/netacea_unified_handler.md new file mode 100644 index 0000000..d044bbc --- /dev/null +++ b/docs/netacea_unified_handler.md @@ -0,0 +1,27 @@ +# Netacea Unified Handler + +This document contains instructions on how to deploy the Netacea CloudFront +integration using a single lambda definition that handles three event types. + +This is an alternative to using individual Viewer Request, Viewer Response, +and Origin Response handlers. + +Using the Unified handler is preferred when using Kinesis ingest, +as Kinesis ingest can be performed in the background while other tasks +are handled by the lambda. + +## Deployment + +The Unified Handler can be deployed in the same way as any of the three +individual lambdas would be, as documented in the +[Installation and Configuration](https://docs.netacea.com/netacea-plugin-information/cloudfront/installation-and-configuration) +section. + +However, the Handler should be specified as `NetaceaUnified.handler` +(rather than, for example, ViewerRequest.handler). + +Finally, these three triggers should specify the Unified Handler lambda: + +- Viewer Request (Include body) +- Viewer Response +- Origin Response diff --git a/package-lock.json b/package-lock.json index 86fc4b6..28c2294 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@netacea/cloudfront": "^6.0.69" + "@netacea/cloudfront": "^6.0.71" }, "devDependencies": { "@types/aws-lambda": "^8.10.119", @@ -216,9 +216,9 @@ } }, "node_modules/@netacea/cloudfront": { - "version": "6.0.69", - "resolved": "https://registry.npmjs.org/@netacea/cloudfront/-/cloudfront-6.0.69.tgz", - "integrity": "sha512-hryfhJy2+edn3aN0e+rcNT8MZ6k8AOR+YZXMvHBYN3bq1LcPIw44aVupNF/iFbvR58H9AqeX0svoNLtCwWbdlg==", + "version": "6.0.71", + "resolved": "https://registry.npmjs.org/@netacea/cloudfront/-/cloudfront-6.0.71.tgz", + "integrity": "sha512-xTOHooSNVRmXBdmXgYDU7fNyWx24tyXSRkNPYKw/ZRvcygLwxiVWCV3hT+mlspl91xLY3+jululLrl7JgsJNeg==", "license": "ISC", "dependencies": { "@types/aws-lambda": "^8.10.138", diff --git a/package.json b/package.json index b767d9b..453a7b9 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "xo": "^0.55.0" }, "dependencies": { - "@netacea/cloudfront": "^6.0.69" + "@netacea/cloudfront": "^6.0.71" }, "xo": { "space": true, diff --git a/src/NetaceaUnified.ts b/src/NetaceaUnified.ts new file mode 100644 index 0000000..cfc64a6 --- /dev/null +++ b/src/NetaceaUnified.ts @@ -0,0 +1,89 @@ +/** + * This file provides an example of how to use a single lambda definition + * to handle multiple event types in AWS CloudFront. + * Please see docs/netacea_unified_handler.md for more information. + */ +import { + type CloudFrontResponse, + type CloudFrontResponseEvent, + type Callback, + type CloudFrontRequest, + type CloudFrontRequestEvent, + type CloudFrontResultResponse, + type Context, + type Handler +} from 'aws-lambda' + +import { + Cloudfront as NetaceaCloudfront, + type CloudfrontConstructorArgs +} from '@netacea/cloudfront' + +import * as NetaceaConfig from './NetaceaConfig.json' + +type EventType = 'origin-request' | 'origin-response' | 'viewer-request' | 'viewer-response' + +const worker = new NetaceaCloudfront(NetaceaConfig as CloudfrontConstructorArgs) + +export const handler: Handler = async ( + event: CloudFrontRequestEvent, + context: Context, + callback: Callback +): Promise => { + context.callbackWaitsForEmptyEventLoop = false + + const eventType = event.Records[0]?.cf.config.eventType?.toLowerCase() as EventType + + if (eventType === 'viewer-request' || eventType === 'origin-request') { + return await viewerRequestHandler(event, context, callback) + } + + if (eventType === 'origin-response') { + return await originResponseHandler(event, context, callback) + } + + if (eventType === 'viewer-response') { + return await viewerResponseHandler(event, context, callback) + } +} + +export const viewerRequestHandler: Handler = async ( + event: CloudFrontRequestEvent, + context: Context, + callback: Callback +): Promise => { + const netaceaResponse = await worker.run(event) + + if (netaceaResponse.respondWith !== undefined) { + callback(null, netaceaResponse.respondWith) + return + } + + callback(null, event.Records[0].cf.request) +} + +export const originResponseHandler: Handler = async ( + event: CloudFrontResponseEvent, + context: Context, + callback: Callback +): Promise => { + if (Number(event.Records[0].cf.response.status) >= 400) { + worker.addNetaceaCookiesToResponse(event) + void worker.ingest(event) + } + + callback(null, event.Records[0].cf.response) +} + +export const viewerResponseHandler: Handler = async ( + event: CloudFrontResponseEvent, + context: Context, + callback: Callback +): Promise => { + if (Number(event.Records[0].cf.response.status) < 400) { + worker.addNetaceaCookiesToResponse(event) + void worker.ingest(event) + } + + callback(null, event.Records[0].cf.response) +} From 694f5d4d37a48eff7e5428d6613523d5ace581ca Mon Sep 17 00:00:00 2001 From: Richard Walkden Date: Thu, 17 Jul 2025 12:31:44 +0100 Subject: [PATCH 2/2] linting --- src/NetaceaUnified.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/NetaceaUnified.ts b/src/NetaceaUnified.ts index cfc64a6..c017809 100644 --- a/src/NetaceaUnified.ts +++ b/src/NetaceaUnified.ts @@ -11,14 +11,12 @@ import { type CloudFrontRequestEvent, type CloudFrontResultResponse, type Context, - type Handler + type Handler, } from 'aws-lambda' - import { Cloudfront as NetaceaCloudfront, - type CloudfrontConstructorArgs + type CloudfrontConstructorArgs, } from '@netacea/cloudfront' - import * as NetaceaConfig from './NetaceaConfig.json' type EventType = 'origin-request' | 'origin-response' | 'viewer-request' | 'viewer-response' @@ -28,29 +26,29 @@ const worker = new NetaceaCloudfront(NetaceaConfig as CloudfrontConstructorArgs) export const handler: Handler = async ( event: CloudFrontRequestEvent, context: Context, - callback: Callback + callback: Callback, ): Promise => { context.callbackWaitsForEmptyEventLoop = false const eventType = event.Records[0]?.cf.config.eventType?.toLowerCase() as EventType if (eventType === 'viewer-request' || eventType === 'origin-request') { - return await viewerRequestHandler(event, context, callback) + return viewerRequestHandler(event, context, callback) } if (eventType === 'origin-response') { - return await originResponseHandler(event, context, callback) + return originResponseHandler(event, context, callback) } if (eventType === 'viewer-response') { - return await viewerResponseHandler(event, context, callback) + return viewerResponseHandler(event, context, callback) } } export const viewerRequestHandler: Handler = async ( event: CloudFrontRequestEvent, context: Context, - callback: Callback + callback: Callback, ): Promise => { const netaceaResponse = await worker.run(event) @@ -65,7 +63,7 @@ export const viewerRequestHandler: Handler = async ( export const originResponseHandler: Handler = async ( event: CloudFrontResponseEvent, context: Context, - callback: Callback + callback: Callback, ): Promise => { if (Number(event.Records[0].cf.response.status) >= 400) { worker.addNetaceaCookiesToResponse(event) @@ -78,7 +76,7 @@ export const originResponseHandler: Handler = async ( export const viewerResponseHandler: Handler = async ( event: CloudFrontResponseEvent, context: Context, - callback: Callback + callback: Callback, ): Promise => { if (Number(event.Records[0].cf.response.status) < 400) { worker.addNetaceaCookiesToResponse(event)