Created
April 14, 2011 01:58
-
-
Save mascarenhas/918768 to your computer and use it in GitHub Desktop.
Proof of concept for FastCGI handler with helper threads
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env lua | |
-- Example application for the FastCGI handler with helper threads | |
local fastcgi = require "thfcgi" | |
local hello = {} | |
local heartbeat = [[ | |
local zmq = require "zmq" | |
local socket = require "socket" | |
local luabins = require "luabins" | |
local ctx = zmq.init_ctx(...) | |
local s = ctx:socket(zmq.REQ) | |
s:connect("inproc://wsapi") | |
local i = 1 | |
while true do | |
socket.sleep(1) | |
s:send(luabins.save("beat", i)) | |
i = i + 1 | |
if s:recv() ~= "ack" then | |
break | |
end | |
end | |
s:close() | |
]] | |
hello.helpers = { heartbeat } | |
function hello.run(wsapi_env) | |
local headers = { ["Content-type"] = "text/html" } | |
local function hello_text() | |
coroutine.yield("<html><body>") | |
coroutine.yield("<p>Hello Wsapi!</p>") | |
coroutine.yield("<p>PATH_INFO: " .. wsapi_env.PATH_INFO .. "</p>") | |
coroutine.yield("<p>SCRIPT_NAME: " .. wsapi_env.SCRIPT_NAME .. "</p>") | |
coroutine.yield("</body></html>") | |
end | |
return 200, headers, coroutine.wrap(hello_text) | |
end | |
function hello:beat(i) | |
local log = io.open("/tmp/hello.tmp", "a+") | |
log:write("Heartbeat " .. i .. "\n") | |
log:close() | |
end | |
fastcgi.run(hello) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
------------------------------------------------------------- | |
--- Proof of concept for FastCGI handler with helper threads | |
------------------------------------------------------------- | |
local llthreads = require "llthreads" | |
local lfcgi = require "lfcgi" | |
local os = require "os" | |
local io = require "io" | |
local common = require "wsapi.common" | |
local zmq = require "zmq" | |
local luabins = require "luabins" | |
local ipairs = ipairs | |
local print = print | |
local type = type | |
local select = select | |
local pcall = pcall | |
local unpack = unpack | |
local _M = {} | |
io.stdout = lfcgi.stdout | |
io.stderr = lfcgi.stderr | |
io.stdin = lfcgi.stdin | |
local accept = [=[ | |
local lfcgi = require "lfcgi" | |
local zmq = require "zmq" | |
local luabins = require "luabins" | |
local ctx = zmq.init_ctx(...) | |
local s = ctx:socket(zmq.REQ) | |
s:connect("inproc://wsapi") | |
while lfcgi.accept() >= 0 do | |
s:send(luabins.save("accept")) | |
if s:recv() ~= "ack" then | |
break | |
end | |
end | |
s:close() | |
]=] | |
-- Runs an WSAPI application for each FastCGI request that comes | |
-- from the FastCGI pipeline | |
function _M.run(app) | |
if type(app) == "function" then | |
app = { helpers = {}, run = app } | |
end | |
local ctx = zmq.init(1) | |
local s = ctx:socket(zmq.REP) | |
s:bind("inproc://wsapi") | |
local threads = {} | |
threads.accept = llthreads.new(accept, ctx:lightuserdata()) | |
threads.accept:start() | |
for i, code in ipairs(app.helpers) do | |
threads[i] = llthreads.new(code, ctx:lightuserdata()) | |
threads[i]:start() | |
end | |
while true do | |
local msg = { luabins.load(s:recv()) } | |
if not msg[1] then | |
error(msg[2]) | |
end | |
local method = msg[2] | |
if method == "accept" then | |
local headers | |
local function getenv(n) | |
if n == "headers" then | |
if headers then return headers end | |
local env_vars = lfcgi.environ() | |
headers = {} | |
for _, s in ipairs(env_vars) do | |
local name, val = s:match("^([^=]+)=(.*)$") | |
headers[name] = val | |
end | |
return headers | |
else | |
return lfcgi.getenv(n) or os.getenv(n) | |
end | |
end | |
common.run(app, { input = lfcgi.stdin, | |
output = lfcgi.stdout, | |
error = lfcgi.stderr, | |
env = getenv }) | |
s:send("ack") | |
else | |
local ok, err = pcall(app[method], app, select(3, unpack(msg))) | |
if ok then | |
s:send("ack") | |
else | |
s:send(err) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment