WebP, content negotiation and CloudFront
AWS recently launched improvements to the CloudFront CDN service. The most important change is the option to specify more HTTP headers be part of the cache key for cached content. This lets you run CloudFront in front of apps that do sophisticated Content Negotiation. In this post, we demonstrate how to use this new power to selectively serve WebP or JPEG encoded images through CloudFront depending on client support. It is a follow-up to my previous post on Serving WebP images with ASP.NET. Combining WebP and CloudFront CDN makes your app faster because users with supported browsers get highly compressed WebP images from AWS’ fast and geo-distributed CDN.
The objective of WebP/JPEG content negotiation is to send WebP encoded images to newer browsers that support it, while falling back to JPEG for older browser without WebP support. Browsers communicate WebP support through the Accept
HTTP header. If the Accept
header value for a request includes image/webp
, we can send WebP encoded images in responses.
Prior to the CloudFront improvements, doing WebP/JPEG content negotiation for images fronted with CloudFront CDN was not possible. That’s because CloudFront would only vary response content based on the Accept-Encoding
header (and some other unrelated properties). With the new improvements, we can configure arbitrary headers for CloudFront to cache on. For WebP/JPEG content negotiation, we specify Accept
in list list of headers to whitelist in the AWS CloudFront console.

Once the rest of the origin and behavior configuration is complete, we can use cURL to test that CloudFront correctly caches and serves responses based on the Accept
request header:
curl -v http://abcd1234.cloudfront.net/myimageurl > /dev/null ... < HTTP/1.1 200 OK < Content-Type: image/jpeg ...
And simulating a client that supports WebP:
curl -v -H "Accept: image/webp" http://abcd1234.cloudfront.net/myimageurl > /dev/null ... < HTTP/1.1 200 OK < Content-Type: image/webp ...
Your origin server should set the Vary
header to let any caches in the response-path know how they can cache, although I don’t believe it’s required to make CloudFront work. In our case, the correct Vary
header value is Accept,Accept-Encoding
.
That’s it! Site visitors will now be receiving compact WebP images (if their browsers support them), served by AWS CloudFront CDN.
4 thoughts on “WebP, content negotiation and CloudFront”-
-
-
-
Benjamin says:
Hello, it does not work for us despite we have white listed Accept, Authorization and Origin.
Adam says:
Accept header was exactly what I needed to get my thumbor images working with webp and cloudfront. Thank you for taking the time to make this valuable information.
Cyril CHAPON says:
Hey, great article
> Once the rest of the origin and behavior configuration is complete
What do you mean here ?
My point is, how do you configure it to actually serve webp uppon Accept header detection, and also set Vary header ?
EDIT: Actualy I realized that I have CloudFront in front of S3, which is not the case in this article
Alex says:
The “accept” header that Chrome send to Cloudfront is:
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
But it is still returning a jpeg image.
And… I already invalidated the cache.
Do I HAVE to change anything on origin?