tmueller@227
|
1 |
-------------------------------------------------------------------------------
|
tmueller@201
|
2 |
--
|
tmueller@201
|
3 |
-- tek.class.fastcgi
|
tmueller@201
|
4 |
-- Written by Timm S. Mueller <tmueller@neoscientists.org>
|
tmueller@201
|
5 |
--
|
tmueller@227
|
6 |
-- OVERVIEW::
|
tmueller@201
|
7 |
-- Lua FastCGI protocol implementation - specifically written for
|
tmueller@227
|
8 |
-- the ''external server'' configuration (via IP socket).
|
tmueller@201
|
9 |
--
|
tmueller@227
|
10 |
-- Methods that must be implemented by the user:
|
tmueller@227
|
11 |
-- - FastCGI:have_params() - signals that all arguments have been
|
tmueller@227
|
12 |
-- transferred
|
tmueller@201
|
13 |
--
|
tmueller@227
|
14 |
-- Methods that can be implemented by the user:
|
tmueller@227
|
15 |
-- - FastCGI:update_stream() - stream created/updated (for POST)
|
tmueller@227
|
16 |
-- - FastCGI:have_stream() - stream completed (for POST)
|
tmueller@201
|
17 |
--
|
tmueller@227
|
18 |
-- REQUIREMENTS::
|
tmueller@227
|
19 |
-- LuaSocket and Bit library
|
tmueller@227
|
20 |
--
|
tmueller@227
|
21 |
-------------------------------------------------------------------------------
|
tmueller@201
|
22 |
|
tmueller@201
|
23 |
local Class = require "tek.class"
|
tmueller@201
|
24 |
local socket = require "socket"
|
tmueller@201
|
25 |
local bit = require "bit"
|
tmueller@201
|
26 |
|
tmueller@201
|
27 |
local insert, remove, concat, pairs, ipairs, error, assert =
|
tmueller@201
|
28 |
table.insert, table.remove, table.concat, pairs, ipairs, error, assert
|
tmueller@201
|
29 |
local tonumber, setmetatable, unpack, type =
|
tmueller@201
|
30 |
tonumber, setmetatable, unpack, type
|
tmueller@201
|
31 |
local char = string.char
|
tmueller@212
|
32 |
local min = math.min
|
tmueller@201
|
33 |
|
tmueller@201
|
34 |
module("tek.class.fastcgi", Class)
|
tmueller@227
|
35 |
_VERSION = "FastCGI 0.4"
|
tmueller@201
|
36 |
|
tmueller@201
|
37 |
-------------------------------------------------------------------------------
|
tmueller@201
|
38 |
-- local FIFO class:
|
tmueller@201
|
39 |
-------------------------------------------------------------------------------
|
tmueller@201
|
40 |
|
tmueller@201
|
41 |
local FIFO = Class:newClass()
|
tmueller@201
|
42 |
|
tmueller@201
|
43 |
function FIFO.new(class, self)
|
tmueller@201
|
44 |
self = Class.new(class, self or { })
|
tmueller@201
|
45 |
self.buf = self.buf or { }
|
tmueller@201
|
46 |
return self
|
tmueller@201
|
47 |
end
|
tmueller@201
|
48 |
|
tmueller@201
|
49 |
function FIFO:write(s)
|
tmueller@201
|
50 |
if s and s ~= -1 then
|
tmueller@201
|
51 |
insert(self.buf, s)
|
tmueller@201
|
52 |
elseif self.buf[#self.buf] ~= -1 then
|
tmueller@201
|
53 |
insert(self.buf, -1) -- EOF
|
tmueller@201
|
54 |
end
|
tmueller@201
|
55 |
end
|
tmueller@201
|
56 |
|
tmueller@201
|
57 |
function FIFO:readn(len)
|
tmueller@201
|
58 |
local t, p, l = { }
|
tmueller@201
|
59 |
while len > 0 do
|
tmueller@201
|
60 |
p = remove(self.buf, 1)
|
tmueller@201
|
61 |
if not p then
|
tmueller@201
|
62 |
break -- no more data
|
tmueller@201
|
63 |
end
|
tmueller@201
|
64 |
if p == -1 then
|
tmueller@201
|
65 |
insert(self.buf, -1) -- push back EOF
|
tmueller@201
|
66 |
break -- end of stream, EOF in next turn
|
tmueller@201
|
67 |
end
|
tmueller@201
|
68 |
l = p:len()
|
tmueller@201
|
69 |
if l > len then -- break buffer fragment in two
|
tmueller@201
|
70 |
insert(t, p:sub(1, len))
|
tmueller@201
|
71 |
insert(self.buf, 1, p:sub(len + 1))
|
tmueller@201
|
72 |
break
|
tmueller@201
|
73 |
end
|
tmueller@201
|
74 |
insert(t, p)
|
tmueller@201
|
75 |
len = len - l
|
tmueller@201
|
76 |
end
|
tmueller@201
|
77 |
return concat(t)
|
tmueller@201
|
78 |
end
|
tmueller@201
|
79 |
|
tmueller@201
|
80 |
function FIFO:reada()
|
tmueller@201
|
81 |
local last = remove(self.buf)
|
tmueller@201
|
82 |
if last ~= -1 then -- not EOF
|
tmueller@201
|
83 |
insert(self.buf, last) -- push back
|
tmueller@201
|
84 |
last = nil
|
tmueller@201
|
85 |
end
|
tmueller@201
|
86 |
local s = concat(self.buf)
|
tmueller@201
|
87 |
self.buf = { last }
|
tmueller@201
|
88 |
return s
|
tmueller@201
|
89 |
end
|
tmueller@201
|
90 |
|
tmueller@201
|
91 |
function FIFO:read(...)
|
tmueller@201
|
92 |
if self.buf[1] == -1 then
|
tmueller@201
|
93 |
return -- EOF
|
tmueller@201
|
94 |
end
|
tmueller@201
|
95 |
local t, s = { }
|
tmueller@201
|
96 |
for _, what in ipairs(arg) do
|
tmueller@201
|
97 |
if what == "*a" then
|
tmueller@201
|
98 |
s = self:reada()
|
tmueller@201
|
99 |
elseif type(what) == "number" then
|
tmueller@201
|
100 |
s = self:readn(tonumber(what))
|
tmueller@201
|
101 |
else
|
tmueller@201
|
102 |
error("unknwon format")
|
tmueller@201
|
103 |
end
|
tmueller@201
|
104 |
insert(t, s)
|
tmueller@201
|
105 |
end
|
tmueller@201
|
106 |
return unpack(t)
|
tmueller@201
|
107 |
end
|
tmueller@201
|
108 |
|
tmueller@201
|
109 |
-- FCGI encoded lengths and key/value pairs:
|
tmueller@201
|
110 |
|
tmueller@201
|
111 |
function FIFO:readlen()
|
tmueller@201
|
112 |
local l = self:read(1)
|
tmueller@201
|
113 |
if not l then return end
|
tmueller@201
|
114 |
l = l:byte()
|
tmueller@201
|
115 |
if l < 128 then
|
tmueller@201
|
116 |
return l
|
tmueller@201
|
117 |
end
|
tmueller@201
|
118 |
local t = self:read(3)
|
tmueller@201
|
119 |
if not t then return end
|
tmueller@201
|
120 |
return (l % 128) * 16777216 + t:byte(1) * 65536 +
|
tmueller@201
|
121 |
t:byte(2) * 256 + t:byte(3)
|
tmueller@201
|
122 |
end
|
tmueller@201
|
123 |
|
tmueller@201
|
124 |
function FIFO:readkeyvals()
|
tmueller@201
|
125 |
local t = { }
|
tmueller@201
|
126 |
local l1, l2, key, val
|
tmueller@201
|
127 |
while true do
|
tmueller@201
|
128 |
l1 = self:readlen()
|
tmueller@201
|
129 |
if not l1 then break end
|
tmueller@201
|
130 |
l2 = self:readlen()
|
tmueller@201
|
131 |
if not l2 then break end
|
tmueller@201
|
132 |
key = self:read(l1)
|
tmueller@201
|
133 |
val = self:read(l2)
|
tmueller@201
|
134 |
t[key] = val
|
tmueller@201
|
135 |
end
|
tmueller@201
|
136 |
return t
|
tmueller@201
|
137 |
end
|
tmueller@201
|
138 |
|
tmueller@201
|
139 |
-------------------------------------------------------------------------------
|
tmueller@201
|
140 |
-- FCGI class:
|
tmueller@201
|
141 |
-------------------------------------------------------------------------------
|
tmueller@201
|
142 |
|
tmueller@201
|
143 |
FCGI_BEGIN_REQUEST = 1
|
tmueller@201
|
144 |
FCGI_ABORT_REQUEST = 2
|
tmueller@201
|
145 |
FCGI_END_REQUEST = 3
|
tmueller@201
|
146 |
FCGI_PARAMS = 4
|
tmueller@201
|
147 |
FCGI_STDIN = 5
|
tmueller@201
|
148 |
FCGI_STDOUT = 6
|
tmueller@201
|
149 |
FCGI_STDERR = 7
|
tmueller@201
|
150 |
FCGI_DATA = 8
|
tmueller@201
|
151 |
FCGI_GET_VALUES = 9
|
tmueller@201
|
152 |
FCGI_GET_VALUES_RESULT = 10
|
tmueller@201
|
153 |
FCGI_UNKNOWN_TYPE = 11
|
tmueller@201
|
154 |
|
tmueller@201
|
155 |
local FCGI_RESPONDER = 1
|
tmueller@201
|
156 |
local FCGI_REQUEST_COMPLETE = 0
|
tmueller@201
|
157 |
local FCGI_UNKNOWN_ROLE = 3
|
tmueller@201
|
158 |
|
tmueller@201
|
159 |
local function encodelen(buf, l)
|
tmueller@201
|
160 |
if l > 127 then
|
tmueller@201
|
161 |
insert(buf, char(bit.rshift(bit.band(l, 0x7f000000), 24) + 128))
|
tmueller@201
|
162 |
insert(buf, char(bit.rshift(bit.band(l, 0x00ff0000), 16)))
|
tmueller@201
|
163 |
insert(buf, char(bit.rshift(bit.band(l, 0x0000ff00), 8)))
|
tmueller@201
|
164 |
end
|
tmueller@201
|
165 |
insert(buf, char(bit.band(l, 0xff)))
|
tmueller@201
|
166 |
end
|
tmueller@201
|
167 |
|
tmueller@201
|
168 |
local function encodekeyvals(t)
|
tmueller@201
|
169 |
local buf = { }
|
tmueller@201
|
170 |
for key, val in pairs(t) do
|
tmueller@201
|
171 |
encodelen(buf, key:len())
|
tmueller@201
|
172 |
encodelen(buf, val:len())
|
tmueller@201
|
173 |
insert(buf, key)
|
tmueller@201
|
174 |
insert(buf, val)
|
tmueller@201
|
175 |
end
|
tmueller@201
|
176 |
return concat(buf)
|
tmueller@201
|
177 |
end
|
tmueller@201
|
178 |
|
tmueller@227
|
179 |
local FastCGI = _M
|
tmueller@201
|
180 |
|
tmueller@227
|
181 |
function FastCGI.new(class, self)
|
tmueller@227
|
182 |
self = Class.new(class, self)
|
tmueller@201
|
183 |
self.requests = { }
|
tmueller@201
|
184 |
return self
|
tmueller@201
|
185 |
end
|
tmueller@201
|
186 |
|
tmueller@227
|
187 |
function FastCGI:readrecord()
|
tmueller@201
|
188 |
local t, err = self.socket:receive(8)
|
tmueller@201
|
189 |
if not t then return end
|
tmueller@201
|
190 |
if err then error(err) end
|
tmueller@201
|
191 |
local r = {
|
tmueller@201
|
192 |
ver = t:byte(1),
|
tmueller@201
|
193 |
type = t:byte(2),
|
tmueller@201
|
194 |
id = t:byte(3) * 256 + t:byte(4),
|
tmueller@201
|
195 |
len = t:byte(5) * 256 + t:byte(6)
|
tmueller@201
|
196 |
}
|
tmueller@201
|
197 |
if r.len == 0 then
|
tmueller@201
|
198 |
r.content = ""
|
tmueller@201
|
199 |
else
|
tmueller@201
|
200 |
r.content, err = self.socket:receive(r.len)
|
tmueller@201
|
201 |
if not r.content then return end
|
tmueller@201
|
202 |
if err then error(err) end
|
tmueller@201
|
203 |
end
|
tmueller@201
|
204 |
local pad = t:byte(7)
|
tmueller@201
|
205 |
if pad > 0 then
|
tmueller@201
|
206 |
t, err = self.socket:receive(pad)
|
tmueller@201
|
207 |
if not t then return end
|
tmueller@201
|
208 |
if err then error(err) end
|
tmueller@201
|
209 |
end
|
tmueller@201
|
210 |
return r
|
tmueller@201
|
211 |
end
|
tmueller@201
|
212 |
|
tmueller@227
|
213 |
function FastCGI:write(type, id, s)
|
tmueller@201
|
214 |
local totlen = s:len()
|
tmueller@201
|
215 |
local totpos = 1
|
tmueller@201
|
216 |
while totlen > 0 do
|
tmueller@212
|
217 |
local len = min(totlen, 65535)
|
tmueller@201
|
218 |
local buf = concat {
|
tmueller@201
|
219 |
char(1), -- version
|
tmueller@201
|
220 |
char(type), -- type
|
tmueller@201
|
221 |
char(bit.rshift(id, 8)), -- id1
|
tmueller@201
|
222 |
char(id % 256), -- id0
|
tmueller@201
|
223 |
char(bit.rshift(len, 8)), -- len1
|
tmueller@201
|
224 |
char(len % 256), -- len0
|
tmueller@201
|
225 |
char(0), -- pad = 0
|
tmueller@201
|
226 |
char(0), -- reserved
|
tmueller@201
|
227 |
s:sub(totpos, totpos + len - 1) -- content
|
tmueller@201
|
228 |
}
|
tmueller@201
|
229 |
totpos = totpos + len
|
tmueller@201
|
230 |
totlen = totlen - len
|
tmueller@201
|
231 |
|
tmueller@201
|
232 |
len = buf:len()
|
tmueller@201
|
233 |
local pos, res, err = 1
|
tmueller@201
|
234 |
while pos <= len do
|
tmueller@201
|
235 |
res, err = self.socket:send(buf, pos)
|
tmueller@201
|
236 |
if not res then
|
tmueller@201
|
237 |
return nil, err
|
tmueller@201
|
238 |
end
|
tmueller@201
|
239 |
pos = res + 1
|
tmueller@201
|
240 |
end
|
tmueller@201
|
241 |
end
|
tmueller@201
|
242 |
return true
|
tmueller@201
|
243 |
end
|
tmueller@201
|
244 |
|
tmueller@227
|
245 |
-------------------------------------------------------------------------------
|
tmueller@227
|
246 |
-- success, msg = write_stdout(req_id, data): Write out data on the FastCGI
|
tmueller@227
|
247 |
-- stdout stream, in reply to a request of the given Id. The result is true,
|
tmueller@227
|
248 |
-- indicating success, or nil followed by an error message.
|
tmueller@227
|
249 |
-------------------------------------------------------------------------------
|
tmueller@227
|
250 |
|
tmueller@227
|
251 |
function FastCGI:write_stdout(id, s)
|
tmueller@201
|
252 |
return self:write(FCGI_STDOUT, id, s)
|
tmueller@201
|
253 |
end
|
tmueller@201
|
254 |
|
tmueller@227
|
255 |
function FastCGI:collectstream(r)
|
tmueller@201
|
256 |
local req = self.requests[r.id]
|
tmueller@201
|
257 |
local s = req.streams[r.type]
|
tmueller@201
|
258 |
if not s then
|
tmueller@201
|
259 |
s = FIFO:new()
|
tmueller@201
|
260 |
req.streams[r.type] = s
|
tmueller@201
|
261 |
end
|
tmueller@201
|
262 |
if r.len == 0 then
|
tmueller@201
|
263 |
s:write() -- append EOF
|
tmueller@201
|
264 |
return s, true -- finished
|
tmueller@201
|
265 |
end
|
tmueller@201
|
266 |
s:write(r.content)
|
tmueller@201
|
267 |
return s
|
tmueller@201
|
268 |
end
|
tmueller@201
|
269 |
|
tmueller@227
|
270 |
-------------------------------------------------------------------------------
|
tmueller@227
|
271 |
-- success, msg = endrequest(request[, protstatus[, appstatus]]):
|
tmueller@227
|
272 |
-- Confirms the end of a FastCGI request. Optionally, the application can
|
tmueller@227
|
273 |
-- signify a protocol status (by default, FCGI_REQUEST_COMPLETE) and an
|
tmueller@227
|
274 |
-- application status (by default, 0). See
|
tmueller@227
|
275 |
-- [[FastCGI protocol][http://www.fastcgi.com/devkit/doc/fcgi-spec.html]]
|
tmueller@227
|
276 |
-- specification for details.
|
tmueller@227
|
277 |
-- The result will be true, indicating success, or nil followed by an
|
tmueller@227
|
278 |
-- error message.
|
tmueller@227
|
279 |
-------------------------------------------------------------------------------
|
tmueller@227
|
280 |
|
tmueller@227
|
281 |
function FastCGI:endrequest(req, protstatus, appstatus)
|
tmueller@201
|
282 |
protstatus = protstatus or req.protstatus or FCGI_REQUEST_COMPLETE
|
tmueller@201
|
283 |
appstatus = appstatus or req.appstatus or 0
|
tmueller@201
|
284 |
self.requests[req.id] = nil -- delete request
|
tmueller@201
|
285 |
return self:write(FCGI_END_REQUEST, req.id, concat {
|
tmueller@201
|
286 |
char(bit.rshift(bit.band(appstatus, 0x7f000000), 24)),
|
tmueller@201
|
287 |
char(bit.rshift(bit.band(appstatus, 0x00ff0000), 16)),
|
tmueller@201
|
288 |
char(bit.rshift(bit.band(appstatus, 0x0000ff00), 8)),
|
tmueller@201
|
289 |
char(bit.band(appstatus, 0xff)),
|
tmueller@201
|
290 |
char(protstatus),
|
tmueller@201
|
291 |
char(0), char(0), char(0)
|
tmueller@201
|
292 |
})
|
tmueller@201
|
293 |
end
|
tmueller@201
|
294 |
|
tmueller@227
|
295 |
function FastCGI:newrequest(id, role, flags)
|
tmueller@201
|
296 |
assert(not self.requests[id])
|
tmueller@201
|
297 |
local req = { id = id, role = role, flags = flags, streams = { } }
|
tmueller@201
|
298 |
self.requests[id] = req
|
tmueller@201
|
299 |
return req
|
tmueller@201
|
300 |
end
|
tmueller@201
|
301 |
|
tmueller@227
|
302 |
function FastCGI:processrecord(r)
|
tmueller@201
|
303 |
|
tmueller@201
|
304 |
local c = r.content
|
tmueller@201
|
305 |
local req = self.requests[r.id]
|
tmueller@201
|
306 |
|
tmueller@201
|
307 |
if r.type == FCGI_BEGIN_REQUEST then
|
tmueller@201
|
308 |
assert(not req)
|
tmueller@201
|
309 |
local role = c:byte(1) * 256 + c:byte(2)
|
tmueller@201
|
310 |
if role == FCGI_RESPONDER then
|
tmueller@201
|
311 |
-- new request
|
tmueller@201
|
312 |
local flags = c:byte(3)
|
tmueller@201
|
313 |
req = self:newrequest(r.id, role, flags)
|
tmueller@201
|
314 |
return true -- continue
|
tmueller@201
|
315 |
end
|
tmueller@201
|
316 |
-- unknown role
|
tmueller@201
|
317 |
return self:endrequest(req, FCGI_UNKNOWN_ROLE)
|
tmueller@201
|
318 |
end
|
tmueller@201
|
319 |
|
tmueller@201
|
320 |
if not req then -- request already closed
|
tmueller@201
|
321 |
return true -- continue
|
tmueller@201
|
322 |
end
|
tmueller@201
|
323 |
|
tmueller@201
|
324 |
if r.type == FCGI_ABORT_REQUEST then
|
tmueller@201
|
325 |
return self:abortrequest(req)
|
tmueller@201
|
326 |
|
tmueller@201
|
327 |
elseif r.type == FCGI_GET_VALUES then
|
tmueller@201
|
328 |
local s, fin = self:collectstream(r)
|
tmueller@201
|
329 |
if s and fin then
|
tmueller@201
|
330 |
local res = { }
|
tmueller@201
|
331 |
for k in pairs(s:readkeyvals()) do
|
tmueller@201
|
332 |
if k == "FCGI_MAX_CONNS" then
|
tmueller@201
|
333 |
res.FCGI_MAX_CONNS = "16"
|
tmueller@201
|
334 |
elseif k == "FCGI_MAX_REQS" then
|
tmueller@201
|
335 |
res.FCGI_MAX_CONNS = "32"
|
tmueller@201
|
336 |
elseif k == "FCGI_MAX_REQS" then
|
tmueller@201
|
337 |
res.FCGI_MAX_CONNS = "1"
|
tmueller@201
|
338 |
end
|
tmueller@201
|
339 |
end
|
tmueller@201
|
340 |
res = encodekeyvals(res)
|
tmueller@201
|
341 |
return self:write(FCGI_GET_VALUES_RESULT, 0, res)
|
tmueller@201
|
342 |
end
|
tmueller@201
|
343 |
|
tmueller@201
|
344 |
elseif r.type == FCGI_PARAMS then
|
tmueller@201
|
345 |
local s, fin = self:collectstream(r)
|
tmueller@201
|
346 |
if s and fin then
|
tmueller@201
|
347 |
req.params = s:readkeyvals()
|
tmueller@201
|
348 |
return self:have_params(req, req.params)
|
tmueller@201
|
349 |
end
|
tmueller@201
|
350 |
|
tmueller@201
|
351 |
elseif r.type == self.FCGI_STDIN or r.type == self.FCGI_DATA then
|
tmueller@201
|
352 |
local s, fin = self:collectstream(r)
|
tmueller@201
|
353 |
if fin then
|
tmueller@201
|
354 |
if self.have_stream then
|
tmueller@201
|
355 |
return self:have_stream(req, r.type, s)
|
tmueller@201
|
356 |
end
|
tmueller@201
|
357 |
else
|
tmueller@201
|
358 |
if self.update_stream then
|
tmueller@201
|
359 |
return self:update_stream(req, r.type, s)
|
tmueller@201
|
360 |
end
|
tmueller@201
|
361 |
end
|
tmueller@201
|
362 |
|
tmueller@201
|
363 |
else
|
tmueller@201
|
364 |
-- unknown record
|
tmueller@201
|
365 |
local buf = char(r.type) .. char(0):rep(7)
|
tmueller@201
|
366 |
return self:write(FCGI_UNKNOWN_TYPE, 0, buf)
|
tmueller@201
|
367 |
end
|
tmueller@201
|
368 |
|
tmueller@201
|
369 |
return true -- continue
|
tmueller@201
|
370 |
end
|
tmueller@201
|
371 |
|
tmueller@227
|
372 |
-------------------------------------------------------------------------------
|
tmueller@227
|
373 |
-- serve(socket): Serve the FastCGI protocol on the supplied socket until
|
tmueller@227
|
374 |
-- FastCGI:stop() is called.
|
tmueller@227
|
375 |
-------------------------------------------------------------------------------
|
tmueller@227
|
376 |
|
tmueller@227
|
377 |
function FastCGI:serve(socket)
|
tmueller@201
|
378 |
assert(socket)
|
tmueller@201
|
379 |
self.socket = socket
|
tmueller@201
|
380 |
self.serve = true
|
tmueller@201
|
381 |
while self.serve do
|
tmueller@201
|
382 |
local r = self:readrecord()
|
tmueller@201
|
383 |
if not r then
|
tmueller@201
|
384 |
break
|
tmueller@201
|
385 |
end
|
tmueller@201
|
386 |
if not self:processrecord(r) then
|
tmueller@201
|
387 |
break
|
tmueller@201
|
388 |
end
|
tmueller@201
|
389 |
end
|
tmueller@201
|
390 |
end
|
tmueller@201
|
391 |
|
tmueller@227
|
392 |
-------------------------------------------------------------------------------
|
tmueller@227
|
393 |
-- stop(): Stop acting as a server. This will cause FastCGI:serve() to
|
tmueller@227
|
394 |
-- return.
|
tmueller@227
|
395 |
-------------------------------------------------------------------------------
|
tmueller@227
|
396 |
|
tmueller@227
|
397 |
function FastCGI:stop()
|
tmueller@201
|
398 |
self.serve = false
|
tmueller@201
|
399 |
end
|
tmueller@201
|
400 |
|
tmueller@227
|
401 |
-------------------------------------------------------------------------------
|
tmueller@227
|
402 |
-- success, msg = abortrequest(req_id): Called when the webserver aborts the
|
tmueller@227
|
403 |
-- request of the given Id. The return value is the result from
|
tmueller@227
|
404 |
-- FastCGI:endrequest().
|
tmueller@227
|
405 |
-------------------------------------------------------------------------------
|
tmueller@227
|
406 |
|
tmueller@227
|
407 |
function FastCGI:abortrequest(req)
|
tmueller@201
|
408 |
-- request aborted by webserver, confirm:
|
tmueller@201
|
409 |
return self:endrequest(req)
|
tmueller@201
|
410 |
end
|
tmueller@227
|
411 |
|
tmueller@227
|
412 |
-------------------------------------------------------------------------------
|
tmueller@227
|
413 |
-- continue = have_params(req_id, params):
|
tmueller@227
|
414 |
-- Signals the arrival of all parameters that belong to the request of the
|
tmueller@227
|
415 |
-- given Id; params is a table containing all received parameters as
|
tmueller@227
|
416 |
-- key/value pairs. The return value is a boolean indicating success and,
|
tmueller@227
|
417 |
-- effectively, whether processing of the request should continue.
|
tmueller@227
|
418 |
-- This method must be implemented by the user before anything useful can be
|
tmueller@227
|
419 |
-- done with a FastCGI request.
|
tmueller@227
|
420 |
-------------------------------------------------------------------------------
|