LuaExamples » History » Revision 1
Revision 1/4
| Next »
stbuehler, 2009-12-21 00:00
LuaExamples¶
- Table of contents
- LuaExamples
X-Sendfile version 1¶
This config snippet inserts a lua filter to check for a "X-Sendfile" header; if a non-empty value is found, it will be used as pathname to a file which replaces the content.
The drawback is that "XSendfile:handle" will be called for every data block going to the user, even if there was no "X-Sendfile" header (lua doesn't read the data, it just forwards the chunks, but it still is not optimal).
But this filter can be inserted at any point in your config, even before the content handler.
-- create new class XSendfile local XSendfile = { } XSendfile.__index = XSendfile -- "classmethod" to create new instance function XSendfile:new(vr) -- vr:debug("New XSendfile instance") local o = { handling = 0 } setmetatable(o, self) return o end -- normal method to handle content function XSendfile:handle(vr, outq, inq) -- vr:debug("XSendfile:handle "..self.handling) if self.handling == 1 then -- already sent the file, ignore further input (we closed it already) inq:skip_all() return lighty.HANDLER_GO_ON elseif self.handling == -1 then -- no X-Sendfile header, so just forward content and make sure to close chunkqueues if done outq:steal_all(inq) if inq.is_closed then -- no more input from backend outq.is_closed = true elseif outq.is_closed then -- client (or other filter after us) closed stream inq.is_closed = true end return lighty.HANDLER_GO_ON else if outq.is_closed then -- client (or other filter after us) closed stream inq:skip_all() inq.is_closed = true return lighty.HANDLER_GO_ON end -- check x-sendfile header local xs = vr.resp.headers["X-Sendfile"] if xs and xs ~= "" then -- file specified vr.resp.headers["X-Sendfile"] = nil -- remove header from response -- Add checks for the pathname here vr:debug("XSendfile:handle: pushing file '" .. xs .. "' as content") outq:add({ filename = xs }) outq.is_closed = true inq:skip_all() inq.is_closed = true self.handling = 1 else self.handling = -1 end return lighty.HANDLER_GO_ON end end actions = lighty.filter_out(XSendfile)
X-Sendfile version 2¶
This config snippet waits for the response headers, and replaces the content with the filename found in the "X-Sendfile" header (if it isn't empty).
This version does not need much cpu; it is assumed that the real backend doesn't send the content anyway, and file is sent in one step, so "XFilterDrop:handle" is probably not called very often.
But this version will wait for the response headers in the action, so you need a content handler before it (static, fastcgi, ...).
-- create new class XFilterDrop local XFilterDrop = { } XFilterDrop.__index = XFilterDrop -- "classmethod" to create new instance function XFilterDrop:new(vr) -- vr:debug("New XSendfile instance") local o = { } setmetatable(o, self) return o end -- normal method to handle content function XFilterDrop:handle(vr, outq, inq) -- drop further input (we closed it already) inq:skip_all() return lighty.HANDLER_GO_ON end -- create a new filter which drops all input and adds it to the vrequest -- returns the filter object so you can insert your own content in f.out (it is already closed) local function add_drop_filter(vr) local f = vr:add_filter_out(XFilterDrop:new()) f['in'].is_closed = true f['in']:skip_all() f.out.is_closed = true return f end local function handle_x_sendfile(vr) -- vr:debug("handle x-sendfile") -- wait for response if not vr.has_response then if vr.is_handled then -- vr:debug("x-sendfile: waiting for response headers") return lighty.HANDLER_WAIT_FOR_EVENT else -- vr:debug("No response handler yet, cannot handle X-Sendfile") return lighty.HANDLER_GO_ON end end -- vr:debug("handle x-sendfile: headers available") -- add filter if x-sendfile header is not empty local xs = vr.resp.headers["X-Sendfile"] if xs and xs ~= "" then -- make sure to drop all other content from the backend local f = add_drop_filter(vr) vr.resp.headers["X-Sendfile"] = nil -- remove header from response -- Add checks for the pathname here vr:debug("XSendfile:handle: pushing file '" .. xs .. "' as content") f.out:add({ filename = xs }) end end actions = handle_x_sendfile
Updated by stbuehler almost 15 years ago · 1 revisions