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";