Skip to content

Instantly share code, notes, and snippets.

@fur-q
Created September 14, 2012 12:03
Show Gist options
  • Save fur-q/3721556 to your computer and use it in GitHub Desktop.
Save fur-q/3721556 to your computer and use it in GitHub Desktop.
shorty
require "shorty"
shorty:get("/", function()
local args = { title = "test", content = "IT WORKS" }
return render("index", args)
end)
shorty:get("/headers", function()
local out = {}
for k,v in pairs(req.headers) do
out[#out+1] = k .. ": " .. v
end
return table.concat(out, "\n")
end)
shorty:get("/args/(%d+)", function(n)
return render("args", { num = n })
end)
getmetatable("").__mod = function(s,t)
return type(t)=="table" and string.format(s,unpack(t)) or string.format(s,t)
end
local views = require("shorty.views"):new()
local pairs, setfenv, unpack = pairs, setfenv, unpack
local smatch, tins = string.match, table.insert
-- private
local function write_resp(stat, resp)
if stat >= 400 and not resp then
return ngx.exit(stat)
end
ngx.status = stat
ngx.print(resp)
end
local function make_req()
local req = {}
req.headers = ngx.req.get_headers()
return req
end
-- exposed utility functions
local function header(key, value)
ngx.header[key] = value
end
-- route return functions
local function halt(code, msg)
if not ngx.header["Content-Type"] then header("Content-Type", "text/plain") end
return code or 500, msg
end
local function redirect(uri, code)
if not uri then
error("bad argument #1 to 'redirect'", 1)
end
header("Location", uri)
return code or 301, nil
end
local function render(name, args, opts)
local mt, out = views:render(name, args, opts)
header("Content-Type", mt)
return out
end
-- let's go
local _M = {}
function _M:respond()
local method, uri = ngx.req.get_method(), ngx.var.uri
local match, handler
for _,v in pairs(self.routes[method]) do
match = { smatch(uri, "^" .. v.route .. "$") }
if #match > 0 then
handler = v.cb
break
end
end
if not handler then
return write_resp(halt(404))
end
local env = {}
for k,v in pairs(_G) do env[k] = v end -- shut up
env.render = render
env.halt = halt
env.redirect = redirect
env.req = make_req()
if method == "POST" then
env.params = ngx.req.get_post_args()
else
env.params = ngx.req.get_uri_args()
end
local f = function() return setfenv(handler, env)(unpack(match)) end
local ok, stat, resp = xpcall(f, debug.traceback)
if not ok then
return write_resp(halt(500, stat))
end
ngx.log(ngx.ERR, stat, resp)
if not resp then
stat, resp = 200, stat
end
return write_resp(stat, resp)
end
function _M:new()
local out = {
settings = {},
routes = {}
}
for _,v in pairs { "GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS" } do
out.routes[v] = {}
out[v:lower()] = function(slf, route, cb)
tins(slf.routes[v], { route = route, cb = cb })
end
end
return setmetatable(out, { __index = self })
end
shorty = _M:new()
shorty.respond = shorty.respond
lua_package_path ";;;/path/to/shorty/?.lua";
init_by_lua_file "/path/to/testapp/app.lua";
server {
server_name abc.de;
root /path/to/testapp/public;
location /__views {
alias /path/to/testapp/views;
internal;
}
location / {
try_files $uri @shorty;
}
location @shorty {
content_by_lua "return shorty:respond()";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment