Amazon CloudFront is a content delivery network (CDN) service that allows Lambda functions to be executed at edge locations.
Distribution configuration contains origins and behaviors which are used to define how to cache and deliver content from other services.
Origin is the endpoint definition of the service that is delivered, e.g. S3 bucket or a website.
Behavior defines how the Amazon CloudFront acts when the request hits the service. That is where Lambda@Edge functions are also defined.
Lambda@Edge has four options when the Lambda function is triggered
viewer-request
, when the CloudFront first receives the request from the clientorigin-request
, before the request to the origin serviceorigin-response
, when CloudFront receives the response from the origin serviceviewer-response
, before the response returned to the clientNOTE: Deployments and removals can take up to 30 minutes due to the CloudFront CDN propagation.
IMPORTANT: Due to current Lambda@Edge limitations it's necessary to set the DeletionPolicy
to Retain
for AWS Lambda functions which use the cloudFront
event. The Serverless Framework will do this automatically for you. However bear in mind that you have to delete those AWS Lambda functions manually once you've removed the service via serverless remove
.
MEMORY AND TIMEOUT LIMITS: According to AWS Limits on Lambda@Edge the limits for viewer-request and viewer-response are 128MB memory and 5 seconds timeout and for origin-request and origin-response are 3008MB memory and 30 seconds timeout.
RUNTIME LIMITS: According to AWS Requirements on Lambda@Edge the runtimes supported by Lambda@Edge functions are: Python 3.8
, Python 3.7
, Node.js 14.x
, Node.js 12.x
, Node.js 10.x
.
This will enable your Lambda@Edge function to be called by a CloudFront.
functions:
myLambdaAtEdge:
handler: myLambdaAtEdge.handler
events:
- cloudFront:
eventType: viewer-response
origin: s3://bucketname.s3.amazonaws.com/files
Example handler function that returns timestamp in the response headers. More examples can be found from AWS documentation.
// index.handler
'use strict';
module.exports.handler = (event, context, callback) => {
const response = event.Records[0].cf.response;
const headers = response.headers;
headers['x-serverless-time'] = [{ key: 'x-serverless-time', value: Date.now().toString() }];
return callback(null, response);
};
For more specific setup, origin can be a object, which uses CloudFormation yaml syntax.
The DomainName
and CustomOriginConfig
or S3OriginConfig
are required, for more details about origin setup visit AWS documentation.
functions:
myLambdaAtEdge:
handler: myLambdaAtEdge.handler
events:
- cloudFront:
eventType: viewer-response
pathPattern: /docs*
origin:
DomainName: serverless.com
OriginPath: /framework
CustomOriginConfig:
OriginProtocolPolicy: match-viewer
One of the CloudFront requirements is to include an empty pathPattern
in the setup.
If there is no behavior with an empty pathPattern
in the serverless configuration, serverless will create an additional behavior with an empty pathPattern
pointing to the defined origin.
If there are more than one different origins, it needs to be defined as a default using isDefaultOrigin
flag.
functions:
myLambdaAtEdge:
handler: myLambdaAtEdge.handler
events:
- cloudFront:
eventType: viewer-response
pathPattern: /files*
isDefaultOrigin: true
origin: s3://bucketname.s3.amazonaws.com/files
mySecondLambdaAtEdge:
handler: mySecondLambdaAtEdge.handler
events:
- cloudFront:
eventType: viewer-response
pathPattern: /docs*
origin:
DomainName: serverless.com
OriginPath: /framework
CustomOriginConfig:
OriginProtocolPolicy: match-viewer
To define functions to each event type, the same origin joins the functions to the same behavior.
functions:
myLambdaAtEdgeViewerRequest:
handler: myLambdaAtEdgeViewerRequest.handler
events:
- cloudFront:
eventType: viewer-request
origin: ${self:custom.origins.myWebsiteOrigin}
myLambdaAtEdgeViewerResponse:
handler: myLambdaAtEdgeViewerResponse.handler
events:
- cloudFront:
eventType: viewer-response
origin: ${self:custom.origins.myWebsiteOrigin}
custom:
origins:
myWebsiteOrigin:
DomainName: serverless.com
OriginPath: /framework
CustomOriginConfig:
OriginProtocolPolicy: match-viewer
To use the same function in multiple behaviors, add multiple events into same function.
functions:
myLambdaAtEdge:
handler: myLambdaAtEdge.handler
events:
- cloudFront:
eventType: viewer-response
includeBody: true
origin: s3://bucketname.s3.amazonaws.com/files
- cloudFront:
eventType: viewer-response
pathPattern: /docs*
origin:
DomainName: serverless.com
OriginPath: /framework
CustomOriginConfig:
OriginProtocolPolicy: match-viewer
The default values for behaviors as generated by the serverless are
ViewerProtocolPolicy: allow-all
For more specific behavior setup, behavior object can be set, which uses CloudFormation yaml syntax. More information about behavior setup visit AWS documentation.
functions:
myLambdaAtEdge:
handler: myLambdaAtEdge.handler
events:
- cloudFront:
eventType: viewer-response
origin: s3://bucketname.s3.amazonaws.com/files
behavior:
ViewerProtocolPolicy: https-only
AllowedMethods:
- 'GET'
- 'HEAD'
- 'OPTIONS'
- 'PUT'
- 'PATCH'
- 'POST'
- 'DELETE'
CachedMethods:
- 'GET'
- 'HEAD'
- 'OPTIONS'
For more specific cache behavior setup, you can use CloudFront Cache Policy.
Use provider level cloudFront.cachePolicies
property to define your policies, which uses CloudFormation yaml syntax. For more information about behavior setup visit AWS documentation.
You can then reference your policy within your event using its name.
provider:
cloudFront:
cachePolicies:
myCachePolicy:
MinTTL: 0
MaxTTL: 86000
DefaultTTL: 3600
...
functions:
myLambdaAtEdge:
handler: myLambdaAtEdge.handler
events:
- cloudFront:
eventType: viewer-response
origin: s3://bucketname.s3.amazonaws.com/files
cachePolicy:
name: myCachePolicy
This configuration will create a Cache Policy named servicename-stage-myCachePolicy
.
You can reference AWS Managed Policies using an id
property instead of name
functions:
myLambdaAtEdge:
handler: myLambdaAtEdge.handler
events:
- cloudFront:
eventType: viewer-response
origin: s3://bucketname.s3.amazonaws.com/files
cachePolicy:
id: 658327ea-f89d-4fab-a63d-7e88639e58f6 # references AWS Managed Policy named Managed-CachingOptimized
It is also possible to reference policies with behavior.CachePolicyId
property. When both cachePolicy.id
and behavior.CachePolicyId
are specified, setting from cachePolicy.id
will be used. Similarily, when cachePolicy.name
and behavior.CachePolicyId
are specified, setting from cachePolicy.name
will be used.
functions:
myLambdaAtEdge:
handler: myLambdaAtEdge.handler
events:
- cloudFront:
eventType: viewer-response
origin: s3://bucketname.s3.amazonaws.com/files
behavior:
CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 # references AWS Managed Policy named Managed-CachingOptimized
Amazon CloudFront distribution configurations can be set in the resources block of the serverless.yml, by defining CloudFrontDistribution
.
resources:
Resources:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
PriceClass: PriceClass_100
Aliases:
- mysite.example.com
ViewerCertificate:
AcmCertificateArn: arn:aws:acm:us-east-1:000000000000:certificate/eb96757c-c78e-4843-bb17-2f09747b6f0d
SslSupportMethod: sni-only
CloudFront behaviors have to have unique path pattern that catches the request.
So following setup is not valid because it assumes that behaviors for both events have an empty path pattern.
functions:
myLambdaAtEdge:
handler: myLambdaAtEdge.handler
events:
- cloudFront:
eventType: viewer-request
origin: s3://bucketname.s3.amazonaws.com/files
- cloudFront:
eventType: viewer-request
origin: s3://bucketname.s3.amazonaws.com/other
Product