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);