souin icon indicating copy to clipboard operation
souin copied to clipboard

Range headers

Open garraflavatra opened this issue 4 months ago • 4 comments

Hi, first of all, thanks for this great project!

I use it with Caddy for sites that serve AVIF and WebP images. From time to time, some of them would disappear, somehow specifically (only) those on Astro sites using the Node.js adapter. I would then purge the cache and all was fine again, until, after some time, they would disappear again.

Turns out, the bottleneck was that some image's responses were ranged: Content-Range: bytes 0-499/12345

I suspect the following:

  • Some browsers/clients somehow send a Range header in their request (despite the images being only a couple of kilobytes).
  • Astro/Node.js already handles this and sends the specified range of bytes in the response.
  • Souin caches this ranged response and sends it for subsequent requests regardless of their Content-Range header.

This seems to be fixed by adding the Range header to the cache key. Perhaps this could be default (just as the Authorization and Cookie headers are always a reason to vary caching)?

garraflavatra avatar Sep 21 '25 15:09 garraflavatra

Hi @garraflavatra I thought everything was working when I implemented the Range support. So now, I'll fetch the entire response before storing it in the cache.

Can you try this commit 0db262873f2f87ac5575438239e357563bd10626 please?

xcaddy build --with github.com/darkweak/souin/plugins/caddy@0db262873f2f87ac5575438239e357563bd10626 --with github.com/darkweak/souin@0db262873f2f87ac5575438239e357563bd10626

darkweak avatar Sep 21 '25 16:09 darkweak

It works! Or at least, it passes the test I did before to replicate it.

Thanks for the wildly fast fix :tada: I see you already had the idea :)

Image

garraflavatra avatar Sep 21 '25 18:09 garraflavatra

That’d be better to keep the actual behavior because it means the cache system will pull the entire resource even if the client ask for a one byte range. That's a temporary fix but I'll improve it later, at least it's working and doesn't break anything else. Can you paste the test you're running to replicate? I'll add it to the test suite to be sure it works after the next improvement.

darkweak avatar Sep 21 '25 19:09 darkweak

True, good point.

What I tested:

  1. Purge the cache
  2. Request with range header to see if sliced response ends up in cache: curl -H "Range: bytes=0-499" --show-headers --output - https://image.avif
  3. Again, without explicit range header: curl --show-headers https://image.avif --> if this is a valid image or has more than 500 bytes, it works. If it doesn't, the sliced response is in the cache.

garraflavatra avatar Sep 21 '25 19:09 garraflavatra