Mercurial > prosody-hg
comparison plugins/mod_http_file_share.lua @ 14073:dfbc60d47668 13.0
mod_http_file_share: Improve handling of Range requests
There were reports of clients always including the Range header, even
when not resuming a download. Since it is equivalent to a non-Range
request, better to simply send the whole file instead of an error.
Range requests with units other than bytes are also ignored now.
RFC 9110 states:
> An origin server MUST ignore a Range header field that contains a
> range unit it does not understand.
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Fri, 13 Feb 2026 14:54:57 +0100 |
| parents | 9974b210d620 |
| children | b688908622a1 |
comparison
equal
deleted
inserted
replaced
| 14070:d7f2ffc25273 | 14073:dfbc60d47668 |
|---|---|
| 429 return 410; | 429 return 410; |
| 430 end | 430 end |
| 431 | 431 |
| 432 local request_range = request.headers.range; | 432 local request_range = request.headers.range; |
| 433 local response_range; | 433 local response_range; |
| 434 if request_range then | 434 -- "bytes=0-" just means "the whole file", so ignore it along with non-byte-range requests |
| 435 local last_byte = string.format("%d", tonumber(filesize) - 1); | 435 if request_range and request_range ~= "bytes=0-" and request_range:find("^bytes=") then |
| 436 local size = tonumber(filesize); | |
| 437 local last_byte = string.format("%d", size - 1); | |
| 436 local range_start, range_end = request_range:match("^bytes=(%d+)%-(%d*)$") | 438 local range_start, range_end = request_range:match("^bytes=(%d+)%-(%d*)$") |
| 437 -- Only support resumption, ie ranges from somewhere in the middle until the end of the file. | 439 -- Only support resumption, ie ranges from somewhere in the middle until the end of the file. |
| 438 if (range_start and range_start ~= "0") and (range_end == "" or range_end == last_byte) then | 440 if range_end == "" or range_end == last_byte then |
| 439 local pos, size = tonumber(range_start), tonumber(filesize); | 441 local pos = tonumber(range_start); |
| 440 local new_pos = pos < size and handle:seek("set", pos); | 442 local new_pos = pos < size and handle:seek("set", pos); |
| 441 if new_pos and new_pos < size then | 443 if new_pos and new_pos < size then |
| 442 response_range = "bytes "..range_start.."-"..last_byte.."/"..filesize; | 444 response_range = string.format("bytes %d-%d/%s", range_start, last_byte, filesize); |
| 443 filesize = string.format("%d", size-pos); | 445 filesize = string.format("%d", size-pos); |
| 444 else | 446 else |
| 445 handle:close(); | 447 handle:close(); |
| 446 return 416; | 448 return 416; |
| 447 end | 449 end |
| 448 else | |
| 449 handle:close(); | |
| 450 return 416; | |
| 451 end | 450 end |
| 452 end | 451 end |
| 453 | 452 |
| 454 | 453 |
| 455 if not filetype then | 454 if not filetype then |
