Mercurial > prosody-hg
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 |
| parents | 7adda14945ad |
| children | 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"; |
