Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions docs/netacea_unified_handler.md
Original file line number Diff line number Diff line change
@@ -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
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"xo": "^0.55.0"
},
"dependencies": {
"@netacea/cloudfront": "^6.0.69"
"@netacea/cloudfront": "^6.0.71"
},
"xo": {
"space": true,
Expand Down
87 changes: 87 additions & 0 deletions src/NetaceaUnified.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* 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<CloudFrontRequest | CloudFrontResultResponse>,
): Promise<void> => {
context.callbackWaitsForEmptyEventLoop = false

const eventType = event.Records[0]?.cf.config.eventType?.toLowerCase() as EventType

if (eventType === 'viewer-request' || eventType === 'origin-request') {
return viewerRequestHandler(event, context, callback)
}

if (eventType === 'origin-response') {
return originResponseHandler(event, context, callback)
}

if (eventType === 'viewer-response') {
return viewerResponseHandler(event, context, callback)
}
}

export const viewerRequestHandler: Handler = async (
event: CloudFrontRequestEvent,
context: Context,
callback: Callback<CloudFrontRequest | CloudFrontResultResponse>,
): Promise<void> => {
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<CloudFrontResponse>,
): Promise<void> => {
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<CloudFrontResponse>,
): Promise<void> => {
if (Number(event.Records[0].cf.response.status) < 400) {
worker.addNetaceaCookiesToResponse(event)
void worker.ingest(event)
}

callback(null, event.Records[0].cf.response)
}