mod_http_file_share: Support download resumption via Range requests
authorKim Alvefur <zash@zash.se>
Sun, 16 May 2021 16:52:59 +0200
changeset 11568 60e31c9ece57
parent 11567 0983653cbfdf
child 11571 c471e19a238e
mod_http_file_share: Support download resumption via Range requests Only a starting point is supported due to the way response:send_file() sends everything it gets from the provided file handle but does not have any way to specify how much to read. This matches what Conversations appears to be doing.
doc/doap.xml
plugins/mod_http_file_share.lua
--- a/doc/doap.xml	Wed May 12 01:11:42 2021 +0200
+++ b/doc/doap.xml	Sun May 16 16:52:59 2021 +0200
@@ -52,6 +52,7 @@
     <implements rdf:resource="https://www.rfc-editor.org/info/rfc6121"/>
     <implements rdf:resource="https://www.rfc-editor.org/info/rfc6122"/>
     <implements rdf:resource="https://www.rfc-editor.org/info/rfc6455"/>
+    <implements rdf:resource="https://www.rfc-editor.org/info/rfc7233"/>
     <implements rdf:resource="https://www.rfc-editor.org/info/rfc7301"/>
     <implements rdf:resource="https://www.rfc-editor.org/info/rfc7395"/>
     <implements rdf:resource="https://www.rfc-editor.org/info/rfc7590"/>
--- a/plugins/mod_http_file_share.lua	Wed May 12 01:11:42 2021 +0200
+++ b/plugins/mod_http_file_share.lua	Sun May 16 16:52:59 2021 +0200
@@ -356,6 +356,20 @@
 		return 410;
 	end
 
+	local request_range = request.headers.range;
+	local response_range;
+	if request_range then
+		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_start ~= filesize) and (range_end == "" or range_end == filesize) then
+			if handle:seek("set", tonumber(range_start)) then
+				response_range = "bytes "..range_start.."-"..filesize.."/"..filesize;
+				filesize = string.format("%d", tonumber(filesize)-tonumber(range_start));
+			end
+		end
+	end
+
+
 	if not filetype then
 		filetype = "application/octet-stream";
 	end
@@ -369,6 +383,12 @@
 	response.headers.content_type = filetype;
 	response.headers.content_disposition = string.format("%s; filename=%q", disposition, basename);
 
+	if response_range then
+		response.status_code = 206;
+		response.headers.content_range = response_range;
+	end
+	response.headers.accept_ranges = "bytes";
+
 	response.headers.cache_control = "max-age=31556952, immutable";
 	response.headers.content_security_policy =  "default-src 'none'; frame-ancestors 'none';"
 	response.headers.strict_transport_security = "max-age=31556952";