15
loading...
This website collects cookies to deliver better user experience
Range
header) and then return the requested subset to the client. This can certainly be suboptimal in some cases such as when the client tries to download the small table of contents at the end of a large video file and ends up waiting while NGINX downloads the entire video before answering the request.proxy_cache_max_range_offset
. Which keeps the range header—but doesn’t cache the response—if the start offset of the requested range is greater than the specified value.Range
header from the origin request, effectively rounding to the entire file. This uses a lot of unnecessary bandwidth (if the rest of the file is not later needed) and can add massive delay when requesting a range far into the file. For example if the client requests data 10GiB into the file they will not receive any content until the proxy has finished downloading the first 10GiB from the origin. (This is the surprising NGINX behaviour described above.)Range
header with the content that the client wants first. (ex: for a server rounding to 10MiB chunks and a request Range: bytes=12345678-20000000
, the proxy could request Range: bytes=12345678-20971519,10485760-12345677
from the origin) However this is unlikely to work in practice as many servers will ignore or reject requests like this. Such a rejection is legal and even somewhat suggested by the RFC.Range
header field that consists of […] many small ranges that are not listed in ascending order, since [it is an indication] of either a broken client or a deliberate denial-of-service attack”. I guess we aren’t requesting “many” ranges out of order but that term is not precisely specified and some real-word proxies ignore all out-of-order requests.Range: bytes=0-99
is made it will be passed to the origin origin and cached. If another request comes in for Range: bytes=0-99
the cache will be used. However if a request is then made for Range: bytes=0-49
it will miss the cache and be passed to the origin. Afterwards bytes 0-49
will be stored twice in the cache, consuming valuable space.Range: bytes=0-99
is made it will be passed to the origin and cached. If a request is then made for Range: bytes=0-49
is made it will be fulfilled from the cache.ETag
you would never be able to build a consistent response. The only way to guarantee a consistent response is to fetch the entire requested range in a single request. In practice range requests from quickly changing files are rare, but I’m sure that you could get a PhD analyzing the performance of different fallback behaviours.If-Range
or If-Match
headers, allowing partial updates until the previously cached content becomes stale.If-Range
mechanism to allow making a range request for a known version with an automatic fallback if the resource has changed. However this header assumes that the desired fallback is the entire resource. This means that it is unsuitable for a partial fill that is fulfilling a range request as in this case the fallback should be the client’s request range, not the entire resource. In this case the only option is to use If-Match
and make a second request if validation fails.Range
requests. The landscape is quite varied. If anyone can test the behaviour of various CDNs I would be happy to update this list.Proxy | Rounding | Matching | Fill |
---|---|---|---|
Amazon CloudFront | Yes | Full | Full |
Cloudflare | Entire File | - | - |
Fastly | Fixed Chunks | Full | Partial |
Google Cloud CDN | Fixed Chunks | Full | Partial |
NGINX default | Entire File | - | - |
NGINX http_proxy_module | Fixed Chunks | Full | Partial |
NGINX proxy_pass Range | None | Exact | - |
NGINX proxy_no_cache | None | None | - |
Range
requests! However based on my own testing they appear to use the default NGINX behaviour of “rounding” to the entire file.ETag
mismatch based on the “Flapping origin entity” error response.Range
request for a given cache key. However if the server supports Range
requests along with a strong ETag
it will then cache future requests. Fill is done via multiple requests of 2MiB-16B each.ETag
mismatch.proxy_pass Range
and adding $http_range
to the cache key can be used to perform exact matching. Alternatively the cache can be disabled for range requests.If-Match
and one request with If-None-Match
in parallel. Most of the time exactly one response will return content. In the rare case that neither return you can resend a full fill and in the rare case that both return content you can abort one.15