aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2021-05-16 16:52:59 +0200
committerKim Alvefur <zash@zash.se>2021-05-16 16:52:59 +0200
commitf5757cae7fff33b74783b8006cbfc1a57ec7c4be (patch)
tree1beabaad97e9c16eb4a500a3f0efd2a0de4ff247
parent8164b929893a089b85be15efd8c599693fef1b7b (diff)
downloadprosody-f5757cae7fff33b74783b8006cbfc1a57ec7c4be.tar.gz
prosody-f5757cae7fff33b74783b8006cbfc1a57ec7c4be.zip
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.
-rw-r--r--doc/doap.xml1
-rw-r--r--plugins/mod_http_file_share.lua20
2 files changed, 21 insertions, 0 deletions
diff --git a/doc/doap.xml b/doc/doap.xml
index 75b4aac8..c62b990f 100644
--- a/doc/doap.xml
+++ b/doc/doap.xml
@@ -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"/>
diff --git a/plugins/mod_http_file_share.lua b/plugins/mod_http_file_share.lua
index 0ef6f856..4b6030bf 100644
--- a/plugins/mod_http_file_share.lua
+++ b/plugins/mod_http_file_share.lua
@@ -356,6 +356,20 @@ function handle_download(event, path) -- GET /uploads/:slot+filename
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 @@ function handle_download(event, path) -- GET /uploads/:slot+filename
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";