Perhaps something like: use a Bypass Cache page rule on the route in question, then use the Cache API to explicitly cache the different responses under different URLs.
But the Bypass cache page rule wouldn’t exist on Cloudflare Free plans which is where the problem lies. For paid plans they’re have Polish/webP conversion so wouldn’t need a workaround.
I think for now until I find a solution, I’ll just disable nginx side webp detection if CF proxy is detected on the nginx origin site so my LEMP stack end users don’t end up with problems when they use CF free plan and have a high portion of Safari browser users where webP isn’t supported but Cloudflare cache ends up serving webP format images from cache to them still.
If it’s just for images needing served by vary header distinction from origin hosted images converted, then Cloudflare does support Vary header for images as outlined at Vary for Images: Serve the Correct Images to the Correct Browsers. Of course this is just for paid Cloudflare plans. So if you don’t need to host varying image formats from origin, then just paid plan Polish would do to serve image format conversions done on the fly at Cloudflare edge.
If on free plan and need to serve varying image formats hosted on origin server via Cloudflare CDN, then easiest way is to serve them with varying extension names image.jpg, image.webp, image.avif and then use img srcset or picture HTML methods to vary the image format served. Or programmatically to do the same via custom Cloudflare worker which inspects the request Accept header for browser/client supported image formats.