Software /
code /
prosody
Comparison
plugins/mod_http_file_share.lua @ 11564:60e31c9ece57
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.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sun, 16 May 2021 16:52:59 +0200 |
parent | 11503:7adda14945ad |
child | 11568:d5360307a99d |
comparison
equal
deleted
inserted
replaced
11563:0983653cbfdf | 11564:60e31c9ece57 |
---|---|
354 -- This can be because the upload slot wasn't used, or the file disappeared | 354 -- This can be because the upload slot wasn't used, or the file disappeared |
355 -- somehow, or permission issues. | 355 -- somehow, or permission issues. |
356 return 410; | 356 return 410; |
357 end | 357 end |
358 | 358 |
359 local request_range = request.headers.range; | |
360 local response_range; | |
361 if request_range then | |
362 local range_start, range_end = request_range:match("^bytes=(%d+)%-(%d*)$") | |
363 -- Only support resumption, ie ranges from somewhere in the middle until the end of the file. | |
364 if (range_start and range_start ~= "0" and range_start ~= filesize) and (range_end == "" or range_end == filesize) then | |
365 if handle:seek("set", tonumber(range_start)) then | |
366 response_range = "bytes "..range_start.."-"..filesize.."/"..filesize; | |
367 filesize = string.format("%d", tonumber(filesize)-tonumber(range_start)); | |
368 end | |
369 end | |
370 end | |
371 | |
372 | |
359 if not filetype then | 373 if not filetype then |
360 filetype = "application/octet-stream"; | 374 filetype = "application/octet-stream"; |
361 end | 375 end |
362 local disposition = "attachment"; | 376 local disposition = "attachment"; |
363 if safe_types:contains(filetype) or safe_types:contains(filetype:gsub("/.*", "/*")) then | 377 if safe_types:contains(filetype) or safe_types:contains(filetype:gsub("/.*", "/*")) then |
366 | 380 |
367 response.headers.last_modified = last_modified; | 381 response.headers.last_modified = last_modified; |
368 response.headers.content_length = filesize; | 382 response.headers.content_length = filesize; |
369 response.headers.content_type = filetype; | 383 response.headers.content_type = filetype; |
370 response.headers.content_disposition = string.format("%s; filename=%q", disposition, basename); | 384 response.headers.content_disposition = string.format("%s; filename=%q", disposition, basename); |
385 | |
386 if response_range then | |
387 response.status_code = 206; | |
388 response.headers.content_range = response_range; | |
389 end | |
390 response.headers.accept_ranges = "bytes"; | |
371 | 391 |
372 response.headers.cache_control = "max-age=31556952, immutable"; | 392 response.headers.cache_control = "max-age=31556952, immutable"; |
373 response.headers.content_security_policy = "default-src 'none'; frame-ancestors 'none';" | 393 response.headers.content_security_policy = "default-src 'none'; frame-ancestors 'none';" |
374 response.headers.strict_transport_security = "max-age=31556952"; | 394 response.headers.strict_transport_security = "max-age=31556952"; |
375 response.headers.x_content_type_options = "nosniff"; | 395 response.headers.x_content_type_options = "nosniff"; |