Cached WebP image is served to browser that doesn't support WebP (Safari 14 on macOS Catalina)

Our website automatically serves WebP images to browsers that support them and regular PNG or JPEG images to browsers that don’t. We’ve run into an issue while using cloudflare caching that is the WebP image being served to Safari 14 on macOS Catalina, which doesn’t support WebP images, although the same version of safari supports WebP images when running on macOS Big Sur.

With development mode on, our website works correctly, serving PNG images to macOS Catalina and WebP images to macOS Big Sur. When we turn on caching, cloudflare doesn’t make a distinction between those two and serves the WebP image incorrectly.

We believe the configuration is correct on our side, and find it strange the CF cache returns a WebP image when the browser doesn’t include it on the Accept header.

We’re using Wordpress with Cloudflare APO enabled and cloudflare plugin installed. We use the WebP Converter for Media plugin to handle WebP images.

Uncached Request and Response headers:

Request
Accept: image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5
Accept-Encoding: gzip, deflate, br
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15

Response
:status: 200
Content-Type: image/png
X-Frame-Options: SAMEORIGIN
Date: Thu, 14 Jan 2021 13:25:32 GMT
Content-Length: 165378
ETag: "28602-5b3705fae633a"
Accept-Ranges: bytes
Last-Modified: Fri, 06 Nov 2020 13:41:46 GMT
cf-request-id: 07a2abb1f90000dbc4cb3aa000000001
Server: cloudflare
cf-cache-status: DYNAMIC
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Strict-Transport-Security: max-age=2592000; includeSubDomains
cf-ray: 6117aefccac7dbc4-GIG

Cached Request and Response headers:

Request
Accept: image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5
Accept-Encoding: gzip, deflate, br
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15

Response
:status: 200
Content-Type: image/webp
Vary: Accept,Referer,X-Forwarded-Proto, Accept-Encoding
ETag: "468a-5b3705fbb24c3"
Age: 2738
Cache-Control: max-age=14400
Date: Thu, 14 Jan 2021 13:22:03 GMT
Content-Length: 18058
Accept-Ranges: bytes
X-Frame-Options: SAMEORIGIN
Last-Modified: Fri, 06 Nov 2020 13:41:47 GMT
Server: cloudflare
cf-request-id: 07a2a880850000dbc4ba0e1000000001
cf-cache-status: HIT
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Strict-Transport-Security: max-age=2592000; includeSubDomains
cf-ray: 6117a9e0ddeadbc4-GIG

Please see:

Thanks for pointing this out. We’ve tried this approach but Polish didn’t work very well for us since it limits to 1000px and we have some very large images.

I’d really like a combination of headers, for example, Vary, that could point cloudflare to caching the two versions of the image.

1 Like

Your examples don’t show a filename. Is this a case where it’s still .jpg or .png, but is actually a WebP? Or does your site alter the HTML depending on the client (changes extensions to .webp)?

I know the docs “recommend” that 1000px limit, but it also says 10MB. Out of curiosity, how large (pixels and filesize) are some of your images?

As for Safari…yeah, I’m looking forward to everybody upgrading to Big Sur so this won’t be a problem.

Hey @sdayman thanks chiming in.

The URL used in the example is https://www.loopkey.com.br/wp-content/uploads/2020/11/loopkey_produtos_bio03.png

The WP plugin WebP Converter for Media uses apache mod_rewrite to internally redirect the request to the webp image (no HTTP redirect) if the request has image/webp in its Accept header. So yes, it just returns the webp image despite the .png extension. I don’t believe this is wrong since the browser sends the Accept: image/webp header, telling the server it will accept a WebP image as a response.

Our largest image in size is 1.26MB, we took care of optimizing them for the web. When activating the Polish feature I actually checked and we got a input_too_large response in the cf-polished header for some images (docs here). That is why I assumed we hit a 1000px limit.

Right now we do not use anything to alter the HTML and change the extensions to .webp, we thought the server-side solution would be more elegant and faster for the client.

I’m activating Polish until we figure this out. Some images will be left out but it is better than nothing. However, I’d still like an answer as to why the Vary header isn’t used to make multiple cached versions of the images, or another alternative to make this work with our server-side solution for switching the images.

However, in this case, Cloudflare is technically the server and will deliver whatever filename you request. And since Cloudflare caches by extension, this is what bites you. If the first person accepts WebP, then that’s what Cloudflare tells the origin. The next request will never reach the server to make this determination. There will be no multiple cached versions, as the url is example.jpg, regardless of filetype.

Ok, then their recommendation probably means that if you don’t follow it, then you won’t get Polish.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.