Configure Amazon CloudFront CDN for WebSocket connection
… for API Gateway WebSocket backend
Concept
Whether you need IPv6 support for your API Gateway API, want to have more points of presence and utilise Amazon’s backbone network as much as possible, or want to transform the requests with Lambda@Edge — Amazon CloudFront CDN in front of API Gateway is your buddy.
CloudFront also support WebSocket connections and becomes a handy tool with Lambda@Edge for solve the limitations of API Gateway with WebSocket endpoint, specifically the lack of path support. However, there are few things to configure before CloudFront can properly handle WebSocket connections.
The first a cache should be disabled completely, the second an origin request policy must allow-list WebSocket-specific headers and the last, requests to an origin must be over HTTPS not just HTTP, as API Gateway doesn’t allow plain HTTP.
Manually
- Create a new Origin Request Policy that Whitelists the following headers:
- Sec-WebSocket-Key
- Sec-WebSocket-Version
- Sec-WebSocket-Protocol
- Sec-WebSocket-Accept
as shown on the image below:
2. Create the distribution that uses API Gateway as an origin, sets HTTPS as protocol to talk to the origin, disables the cache and uses the policy created in the step 1.
That’s it.
With CDK
If you are using AWS CDK, the distribution shall look like this:
// Creating a custom origin request policyconst wsOriginRequestPolicy = new cloudfront.OriginRequestPolicy(this, ‘webSocketPolicy’, {
originRequestPolicyName: ‘webSocketPolicy’,
comment: ‘A default WebSocket policy’,
cookieBehavior: cloudfront.OriginRequestCookieBehavior.none(),
headerBehavior: cloudfront.OriginRequestHeaderBehavior.allowList(“Sec-WebSocket-Key”, “Sec-WebSocket-Version”, “Sec-WebSocket-Protocol”, “Sec-WebSocket-Accept”),
queryStringBehavior: cloudfront.OriginRequestQueryStringBehavior.none(),
});new cloudfront.Distribution(this, ‘myDist’, {
defaultBehavior: {
origin: new origins.HttpOrigin(<domain>,{originPath:<path>}),
cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
originRequestPolicy: wsOriginRequestPolicy,
},
});
Happy coding,
Nick