Software /
code /
prosody
Comparison
plugins/mod_http_file_share.lua @ 11332:3e0dcdf6283e
mod_http_file_share: Cache file metadata
For faster access by avoiding archive ID.
No benchmarks were harmed in the making of this commit.
... no benchmarks were performed at all.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 28 Jan 2021 16:34:13 +0100 |
parent | 11331:7a915fa49373 |
child | 11333:f80056b97cf0 |
comparison
equal
deleted
inserted
replaced
11331:7a915fa49373 | 11332:3e0dcdf6283e |
---|---|
15 local jwt = require "util.jwt"; | 15 local jwt = require "util.jwt"; |
16 local errors = require "util.error"; | 16 local errors = require "util.error"; |
17 local dataform = require "util.dataforms".new; | 17 local dataform = require "util.dataforms".new; |
18 local dt = require "util.datetime"; | 18 local dt = require "util.datetime"; |
19 local hi = require "util.human.units"; | 19 local hi = require "util.human.units"; |
20 local cache = require "util.cache"; | |
20 | 21 |
21 local namespace = "urn:xmpp:http:upload:0"; | 22 local namespace = "urn:xmpp:http:upload:0"; |
22 | 23 |
23 module:depends("disco"); | 24 module:depends("disco"); |
24 | 25 |
52 filesize = { type = "modify"; condition = "not-acceptable"; text = "File too large"; | 53 filesize = { type = "modify"; condition = "not-acceptable"; text = "File too large"; |
53 extra = {tag = st.stanza("file-too-large", {xmlns = namespace}):tag("max-file-size"):text(tostring(file_size_limit)) }; | 54 extra = {tag = st.stanza("file-too-large", {xmlns = namespace}):tag("max-file-size"):text(tostring(file_size_limit)) }; |
54 }; | 55 }; |
55 filesizefmt = { type = "modify"; condition = "bad-request"; text = "File size must be positive integer"; } | 56 filesizefmt = { type = "modify"; condition = "bad-request"; text = "File size must be positive integer"; } |
56 }); | 57 }); |
58 | |
59 local upload_cache = cache.new(1024); | |
57 | 60 |
58 -- Convenience wrapper for logging file sizes | 61 -- Convenience wrapper for logging file sizes |
59 local function B(bytes) return hi.format(bytes, "B", "b"); end | 62 local function B(bytes) return hi.format(bytes, "B", "b"); end |
60 | 63 |
61 local function get_filename(slot, create) | 64 local function get_filename(slot, create) |
212 uploaded, err = false, 413; | 215 uploaded, err = false, 413; |
213 end | 216 end |
214 if uploaded then | 217 if uploaded then |
215 module:log("debug", "Upload of %q completed, %s", filename, B(final_size)); | 218 module:log("debug", "Upload of %q completed, %s", filename, B(final_size)); |
216 assert(os.rename(filename.."~", filename)); | 219 assert(os.rename(filename.."~", filename)); |
220 | |
221 upload_cache:set(upload_info.slot, { | |
222 name = upload_info.filename; | |
223 size = tostring(upload_info.filesize); | |
224 type = upload_info.filetype; | |
225 time = os.time(); | |
226 }); | |
217 return 201; | 227 return 201; |
218 else | 228 else |
219 assert(os.remove(filename.."~")); | 229 assert(os.remove(filename.."~")); |
220 return err; | 230 return err; |
221 end | 231 end |
224 end | 234 end |
225 | 235 |
226 function handle_download(event, path) -- GET /uploads/:slot+filename | 236 function handle_download(event, path) -- GET /uploads/:slot+filename |
227 local request, response = event.request, event.response; | 237 local request, response = event.request, event.response; |
228 local slot_id = path:match("^[^/]+"); | 238 local slot_id = path:match("^[^/]+"); |
229 -- TODO cache | |
230 local basename, filetime, filetype, filesize; | 239 local basename, filetime, filetype, filesize; |
231 local slot, when = errors.coerce(uploads:get(nil, slot_id)); | 240 local cached = upload_cache:get(slot_id); |
232 if not slot then | 241 if cached then |
233 module:log("debug", "uploads:get(%q) --> not-found, %s", slot_id, when); | 242 module:log("debug", "Cache hit"); |
243 -- TODO stats (instead of logging?) | |
244 basename = cached.name; | |
245 filesize = cached.size; | |
246 filetype = cached.type; | |
247 filetime = cached.time; | |
248 upload_cache:set(slot_id, cached); | |
249 -- TODO cache negative hits? | |
234 else | 250 else |
235 basename = slot.attr.filename; | 251 module:log("debug", "Cache miss"); |
236 filesize = slot.attr.size; | 252 local slot, when = errors.coerce(uploads:get(nil, slot_id)); |
237 filetype = slot.attr["content-type"]; | 253 if not slot then |
238 filetime = when; | 254 module:log("debug", "uploads:get(%q) --> not-found, %s", slot_id, when); |
255 else | |
256 module:log("debug", "uploads:get(%q) --> %s, %d", slot_id, slot, when); | |
257 basename = slot.attr.filename; | |
258 filesize = slot.attr.size; | |
259 filetype = slot.attr["content-type"]; | |
260 filetime = when; | |
261 upload_cache:set(slot_id, { | |
262 name = basename; | |
263 size = slot.attr.size; | |
264 type = filetype; | |
265 time = when; | |
266 }); | |
267 end | |
239 end | 268 end |
240 if not basename then | 269 if not basename then |
241 return 404; | 270 return 404; |
242 end | 271 end |
243 module:log("debug", "uploads:get(%q) --> %s, %d", slot_id, slot, when); | |
244 local last_modified = os.date('!%a, %d %b %Y %H:%M:%S GMT', filetime); | 272 local last_modified = os.date('!%a, %d %b %Y %H:%M:%S GMT', filetime); |
245 if request.headers.if_modified_since == last_modified then | 273 if request.headers.if_modified_since == last_modified then |
246 return 304; | 274 return 304; |
247 end | 275 end |
248 local filename = get_filename(slot_id); | 276 local filename = get_filename(slot_id); |
290 local obsolete_files = array(); | 318 local obsolete_files = array(); |
291 local i = 0; | 319 local i = 0; |
292 for slot_id in iter do | 320 for slot_id in iter do |
293 i = i + 1; | 321 i = i + 1; |
294 obsolete_files:push(get_filename(slot_id)); | 322 obsolete_files:push(get_filename(slot_id)); |
323 upload_cache:set(slot_id, nil); | |
295 end | 324 end |
296 | 325 |
297 sleep(0.1); | 326 sleep(0.1); |
298 local n = 0; | 327 local n = 0; |
299 obsolete_files:filter(function(filename) | 328 obsolete_files:filter(function(filename) |