Mercurial > prosody-hg
comparison plugins/mod_http_file_share.lua @ 14077:c83aee2a0b11
mod_http_file_share: Support full Range requests
This allows requesting smaller slices of a file, often done by video
players.
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Fri, 13 Feb 2026 16:19:12 +0100 |
| parents | b688908622a1 |
| children |
comparison
equal
deleted
inserted
replaced
| 14076:a558af9e8c35 | 14077:c83aee2a0b11 |
|---|---|
| 431 return 410; | 431 return 410; |
| 432 end | 432 end |
| 433 | 433 |
| 434 local request_range = request.headers.range; | 434 local request_range = request.headers.range; |
| 435 local response_range; | 435 local response_range; |
| 436 local response_len = nil; -- until eof | |
| 436 -- "bytes=0-" just means "the whole file", so ignore it along with non-byte-range requests | 437 -- "bytes=0-" just means "the whole file", so ignore it along with non-byte-range requests |
| 437 if request_range and request_range ~= "bytes=0-" and request_range:find("^bytes=") then | 438 if request_range and request_range ~= "bytes=0-" and request_range:find("^bytes=") then |
| 438 local size = tonumber(filesize); | 439 local size = tonumber(filesize); |
| 439 local last_byte = string.format("%d", size - 1); | 440 local range_start, range_end = request_range:match("^bytes=(%d*)%-(%d*)$") |
| 440 local range_start, range_end = request_range:match("^bytes=(%d+)%-(%d*)$") | 441 local pos, stop = tonumber(range_start) or 0, tonumber(range_end) or size-1; |
| 441 -- Only support resumption, ie ranges from somewhere in the middle until the end of the file. | 442 if range_start == "" then pos, stop = size - stop, size - 1; end |
| 442 if range_end == "" or range_end == last_byte then | 443 if pos <= stop and stop < size then |
| 443 local pos = tonumber(range_start); | 444 pos = handle:seek("set", pos); |
| 444 local new_pos = pos < size and handle:seek("set", pos); | 445 response_len = stop - pos + 1; |
| 445 if new_pos and new_pos < size then | 446 response_range = string.format("bytes %d-%d/%s", pos, stop, filesize); |
| 446 response_range = string.format("bytes %d-%d/%s", range_start, last_byte, filesize); | 447 filesize = string.format("%d", response_len); |
| 447 filesize = string.format("%d", size-pos); | 448 else |
| 448 else | 449 handle:close(); |
| 449 handle:close(); | 450 module:log("debug", "Invalid range requested: %q", request_range) |
| 450 return 416; | 451 return 416; |
| 451 end | |
| 452 end | 452 end |
| 453 end | 453 end |
| 454 | 454 |
| 455 | 455 |
| 456 if not filetype then | 456 if not filetype then |
| 477 response.headers.strict_transport_security = "max-age=31556952"; | 477 response.headers.strict_transport_security = "max-age=31556952"; |
| 478 response.headers.x_content_type_options = "nosniff"; | 478 response.headers.x_content_type_options = "nosniff"; |
| 479 response.headers.x_frame_options = "DENY"; -- COMPAT IE missing support for CSP frame-ancestors | 479 response.headers.x_frame_options = "DENY"; -- COMPAT IE missing support for CSP frame-ancestors |
| 480 response.headers.x_xss_protection = "1; mode=block"; | 480 response.headers.x_xss_protection = "1; mode=block"; |
| 481 | 481 |
| 482 return response:send_file(handle); | 482 return response:send_file(handle, response_len); |
| 483 end | 483 end |
| 484 | 484 |
| 485 if expiry < math.huge and not external_base_url then | 485 if expiry < math.huge and not external_base_url then |
| 486 -- TODO HTTP DELETE to the external endpoint? | 486 -- TODO HTTP DELETE to the external endpoint? |
| 487 local array = require "prosody.util.array"; | 487 local array = require "prosody.util.array"; |
