2c2821d065580941cb75aaa44997c8ed0505b486
2 * uhttpd - Tiny non-forking httpd - Lua handler
4 * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 #include "uhttpd-utils.h"
21 #include "uhttpd-lua.h"
24 static int uh_lua_recv(lua_State
*L
)
27 char buffer
[UH_LIMIT_MSGHEAD
];
30 struct timeval timeout
;
33 luaL_checktype(L
, 1, LUA_TLIGHTUSERDATA
);
34 cl
= (struct client
*) lua_topointer(L
, 1);
35 length
= luaL_checknumber(L
, 2);
37 if( (cl
!= NULL
) && (length
> 0) && (length
<= sizeof(buffer
)) )
40 FD_SET(cl
->socket
, &reader
);
44 timeout
.tv_usec
= 100000;
46 /* first return stuff from peek buffer */
50 rlen
= uh_tcp_recv(cl
, buffer
, min(cl
->peeklen
, length
));
51 lua_pushnumber(L
, rlen
);
52 lua_pushlstring(L
, buffer
, rlen
);
57 /* check whether fd is readable */
58 else if( select(cl
->socket
+ 1, &reader
, NULL
, NULL
, &timeout
) > 0 )
61 rlen
= uh_tcp_recv(cl
, buffer
, length
);
62 lua_pushnumber(L
, rlen
);
66 lua_pushlstring(L
, buffer
, rlen
);
73 /* no, timeout and actually no data */
74 lua_pushnumber(L
, -2);
79 lua_pushnumber(L
, -3);
83 static int uh_lua_send_common(lua_State
*L
, int chunked
)
90 luaL_checktype(L
, 1, LUA_TLIGHTUSERDATA
);
91 cl
= (struct client
*) lua_topointer(L
, 1);
92 buffer
= luaL_checklstring(L
, 2, &length
);
94 if( (cl
!= NULL
) && (length
> 0) )
97 slen
= uh_http_sendc(cl
, buffer
, length
);
99 slen
= uh_tcp_send(cl
, buffer
, length
);
101 lua_pushnumber(L
, slen
);
105 lua_pushnumber(L
, -1);
109 static int uh_lua_send(lua_State
*L
)
111 return uh_lua_send_common(L
, 0);
114 static int uh_lua_sendc(lua_State
*L
)
116 return uh_lua_send_common(L
, 1);
119 static int uh_lua_urldecode(lua_State
*L
)
121 size_t inlen
, outlen
;
123 char outbuf
[UH_LIMIT_MSGHEAD
];
125 inbuf
= luaL_checklstring(L
, 1, &inlen
);
126 outlen
= uh_urldecode(outbuf
, sizeof(outbuf
), inbuf
, inlen
);
128 lua_pushlstring(L
, outbuf
, outlen
);
133 lua_State
* uh_lua_init(const char *handler
)
135 lua_State
*L
= lua_open();
137 const char *err_str
= NULL
;
139 /* Declare the Lua libraries we wish to use. */
140 /* Note: If you are opening and running a file containing Lua code */
141 /* using 'lua_dofile(l, "myfile.lua") - you must delcare all the libraries */
142 /* used in that file here also. */
143 static const luaL_reg lualibs
[] =
145 { "base", luaopen_base
},
146 { "string", luaopen_string
},
150 /* preload libraries */
151 for (lib
= lualibs
; lib
->func
!= NULL
; lib
++)
157 /* build uhttpd api table */
160 /* register global send and receive functions */
161 lua_pushcfunction(L
, uh_lua_recv
);
162 lua_setfield(L
, -2, "recv");
164 lua_pushcfunction(L
, uh_lua_send
);
165 lua_setfield(L
, -2, "send");
167 lua_pushcfunction(L
, uh_lua_sendc
);
168 lua_setfield(L
, -2, "sendc");
170 lua_pushcfunction(L
, uh_lua_urldecode
);
171 lua_setfield(L
, -2, "urldecode");
173 /* _G.uhttpd = { ... } */
174 lua_setfield(L
, LUA_GLOBALSINDEX
, "uhttpd");
177 /* load Lua handler */
178 switch( luaL_loadfile(L
, handler
) )
182 "Lua handler contains syntax errors, unable to continue\n");
187 "Lua handler ran out of memory, unable to continue\n");
192 "Lua cannot open the handler script, unable to continue\n");
196 /* compile Lua handler */
197 switch( lua_pcall(L
, 0, 0, 0) )
200 err_str
= luaL_checkstring(L
, -1);
202 "Lua handler had runtime error, unable to continue\n"
203 "Error: %s\n", err_str
208 err_str
= luaL_checkstring(L
, -1);
210 "Lua handler ran out of memory, unable to continue\n"
211 "Error: %s\n", err_str
216 /* test handler function */
217 lua_getglobal(L
, UH_LUA_CALLBACK
);
219 if( ! lua_isfunction(L
, -1) )
222 "Lua handler provides no " UH_LUA_CALLBACK
"(), unable to continue\n");
236 void uh_lua_request(struct client
*cl
, struct http_request
*req
, lua_State
*L
)
240 const char *prefix
= cl
->server
->conf
->lua_prefix
;
241 const char *err_str
= NULL
;
243 /* put handler callback on stack */
244 lua_getglobal(L
, UH_LUA_CALLBACK
);
247 /* build env table */
251 lua_pushlightuserdata(L
, (void *)cl
);
252 lua_setfield(L
, -2, "client");
257 case UH_HTTP_MSG_GET
:
258 lua_pushstring(L
, "get");
261 case UH_HTTP_MSG_HEAD
:
262 lua_pushstring(L
, "head");
265 case UH_HTTP_MSG_POST
:
266 lua_pushstring(L
, "post");
270 lua_setfield(L
, -2, "request_method");
273 lua_pushstring(L
, req
->url
);
274 lua_setfield(L
, -2, "request_url");
276 /* query string, path info */
277 if( (query_string
= strchr(req
->url
, '?')) != NULL
)
279 lua_pushstring(L
, query_string
+ 1);
280 lua_setfield(L
, -2, "query_string");
282 if( (int)(query_string
- req
->url
) > strlen(prefix
) )
285 &req
->url
[strlen(prefix
)],
286 (int)(query_string
- req
->url
) - strlen(prefix
)
289 lua_setfield(L
, -2, "path_info");
292 else if( strlen(req
->url
) > strlen(prefix
) )
294 lua_pushstring(L
, &req
->url
[strlen(prefix
)]);
295 lua_setfield(L
, -2, "path_info");
298 /* http protcol version */
299 lua_pushnumber(L
, floor(req
->version
* 10) / 10);
300 lua_setfield(L
, -2, "http_version");
303 /* address information */
304 lua_pushstring(L
, sa_straddr(&cl
->peeraddr
));
305 lua_setfield(L
, -2, "remote_addr");
307 lua_pushinteger(L
, sa_port(&cl
->peeraddr
));
308 lua_setfield(L
, -2, "remote_port");
310 lua_pushstring(L
, sa_straddr(&cl
->servaddr
));
311 lua_setfield(L
, -2, "server_addr");
313 lua_pushinteger(L
, sa_port(&cl
->servaddr
));
314 lua_setfield(L
, -2, "server_port");
320 foreach_header(i
, req
->headers
)
322 lua_pushstring(L
, req
->headers
[i
+1]);
323 lua_setfield(L
, -2, req
->headers
[i
]);
326 lua_setfield(L
, -2, "headers");
330 switch( lua_pcall(L
, 1, 0, 0) )
333 err_str
= luaL_checkstring(L
, -1);
334 uh_http_sendhf(cl
, 500, "Lua runtime error",
335 "Lua raised an error:\n%s\n", err_str
);
339 err_str
= luaL_checkstring(L
, -1);
340 uh_http_sendhf(cl
, 500, "Lua out of memory",
341 "Lua raised an error:\n%s\n", err_str
);