-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsoakbean.lua
227 lines (204 loc) · 5.51 KB
/
soakbean.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
local json = require "json"
function error(str) print("[error] " .. str) end
function keys(table) local i = 0 ; for k, v in pairs(table) do i = i + 1 end ; return i end
sb = {}
sb = {
middleware={},
handler={},
data={},
charset="utf-8",
__index=function(self,k,v)
if sb.data[k] then return sb.data[k] end
if sb[k] then return sb[k] end
return rawget(self,k)
end,
__newindex=function(self,k,v)
if type(v) == "function" then
sb.data[k] = (function(k,v)
return function(a,b,c,d,e,f)
v(a,b,c,d,e,f)
sb.pub(k,v)
end
end)(k,v)
else
sb.data[k] = v
sb.pub(k,v)
end
end,
on = function(k,f)
sb.handler[k] = sb.handler[k] or {}
table.insert( sb.handler[k], f )
return sb.app
end,
pub = function(k,v)
if sb.handler[k] ~= nil then
for i,handler in pairs(sb.handler[k]) do
coroutine.wrap(handler)(v,k)
end
end
end,
-- print( util.tpl("${name} is ${value}", {name = "foo", value = "bar"}) )
-- "foo is bar"
tpl = function(s,tab)
return (s:gsub('($%b{})', function(w) return tab[w:sub(3, -2)] or w end))
end,
write = function(str)
Write( sb.app.tpl(str,sb.app.data) )
end,
job = function(app)
return function(cfg)
-- app.
return app
end
end,
request = function(method, app)
return function(path,f)
app.use( function(req,res,next)
if req.url:match(path) and req.method == method then
f(req,res,next)
else next() end
end)
end
end,
use = function(f)
table.insert(sb.middleware,f)
return sb.app
end,
useDefaults = function(app)
app.use( function(req,res,next)
app.pub(req.url,{req=req,res=res})
next()
end)
end,
run = function(req)
local next = function() end
local k = 0
local req = {
param={},
method=GetMethod(),
host=GetHost(),
header=GetHeaders(),
url=GetPath(),
protocol=GetScheme(),
body={}
}
local res={
_status=nil,
_header={},
_body=""
}
local params = GetParams()
if params ~= nil then
for i,p in pairs(params) do req.param[ p[1] ] = p[2] end
end
res.status = function(status) res._status = status ; sb.pub('res.status',status) end
res.body = function(v) res._body = v ; sb.pub('req.body' ,body) end
res.header = function(k,v)
if v == nil then return res._header[k] end
res._header[k] = v
sb.pub('res.header',{key=k,value=v})
end
res.header("content-type","text/html")
-- run middleware
next = function()
k = k+1
if type(sb.middleware[k]) == "function" then sb.middleware[k](req,res,next) end
end
next()
end,
json = function()
local json_response = function(response)
return function()
return function(req,res,next)
if type(res._body) == "table" then
res.header('content-type',"application/json")
res.body( json.encode(res._body) )
end
response(req,res,next)
end
end
end
sb.response = json_response(sb.response())
return function(req,res,next)
if req.method ~= "GET" and req.header['Content-Type']:match("application/json") and GetPayload():sub(0,1) == "{" then
req.body = json.decode( GetPayload() )
end
next()
end
end,
response = function()
return function(req,res,next)
if res._body ~= nil and res._status ~= nil and res._header['content-type'] ~= nil then
SetStatus(res._status)
for k,v in pairs(res._header) do
if k == "content-type" then v = v .. "; charset=" .. sb.charset end
SetHeader(k,v)
end
if type(res._body) == "string" then
Write( res._body )
else print("[ERROR] res.body is not a string (HINT: use json middleware)") end
else next() end
end
end,
router = function(router)
return function(req,res,next)
for p1, p2 in pairs(router) do
if GetPath():match(p1) then
if type(p2) == "string" then
print("router: " .. p1 .. " => " .. p2)
RoutePath(p2)
end
if type(p2) == "function" then p2(req,res,next) end
sb.pub(p1,req)
sb.pub(p2,req)
return true
end
end
next()
end
end,
template = function(file)
return function(req,res,next)
res.status(200)
res.header('content-type','text/html')
res.body( sb.app.tpl( LoadAsset(file), sb.app ) )
next()
end
end,
init = function(app)
for k,v in pairs(argv) do
app.opts[ v:gsub("=.*","") ] = v:gsub(".*=","")
end
if( keys(app.cmd) > 0 ) then sb.runcmd(app) end
end,
runcmd = function(app)
for k,v in pairs(app.opts) do
if app.cmd[k] then
local file = app.cmd[k].file
return require( file:sub(0,-5) )(app,argv)
end
end
print("\nUsage: " .. app.bin .. " <cmd> [opts]\n\n")
for k,v in pairs(app.cmd) do
print("\t" .. app.bin .. " " .. k .. "\t\t" .. v.info )
end
print("")
os.exit()
end
}
return function(data)
local app = {}
setmetatable(app,sb)
sb.app = app
sb.data = data
sb.data.url = {}
if data.url == nil then sb.data.url = {} end
sb.get = sb.request('GET', app)
sb.post = sb.request('POST', app)
sb.put = sb.request('PUT', app)
sb.options = sb.request('OPTIONS', app)
sb.delete = sb.request('DELETE', app)
sb.init(app)
sb.useDefaults(app)
return app
end