changeset 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 d7f2ffc25273
children b688908622a1 79a6598cef0b
files plugins/mod_http_file_share.lua
diffstat 1 files changed, 7 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/mod_http_file_share.lua	Wed Feb 11 11:38:55 2026 +0000
+++ b/plugins/mod_http_file_share.lua	Fri Feb 13 14:54:57 2026 +0100
@@ -431,23 +431,22 @@
 
 	local request_range = request.headers.range;
 	local response_range;
-	if request_range then
-		local last_byte = string.format("%d", tonumber(filesize) - 1);
+	-- "bytes=0-" just means "the whole file", so ignore it along with non-byte-range requests
+	if request_range and request_range ~= "bytes=0-" and request_range:find("^bytes=") then
+		local size = tonumber(filesize);
+		local last_byte = string.format("%d", size - 1);
 		local range_start, range_end = request_range:match("^bytes=(%d+)%-(%d*)$")
 		-- Only support resumption, ie ranges from somewhere in the middle until the end of the file.
-		if (range_start and range_start ~= "0") and (range_end == "" or range_end == last_byte) then
-			local pos, size = tonumber(range_start), tonumber(filesize);
+		if range_end == "" or range_end == last_byte then
+			local pos = tonumber(range_start);
 			local new_pos = pos < size and handle:seek("set", pos);
 			if new_pos and new_pos < size then
-				response_range = "bytes "..range_start.."-"..last_byte.."/"..filesize;
+				response_range = string.format("bytes %d-%d/%s", range_start, last_byte, filesize);
 				filesize = string.format("%d", size-pos);
 			else
 				handle:close();
 				return 416;
 			end
-		else
-			handle:close();
-			return 416;
 		end
 	end