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(lua_State *L)
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) )
96 slen = uh_tcp_send(cl, buffer, length);
97 lua_pushnumber(L, slen);
101 lua_pushnumber(L, -1);
105 static int uh_lua_urldecode(lua_State *L)
107 size_t inlen, outlen;
109 char outbuf[UH_LIMIT_MSGHEAD];
111 inbuf = luaL_checklstring(L, 1, &inlen);
112 outlen = uh_urldecode(outbuf, sizeof(outbuf), inbuf, inlen);
114 lua_pushlstring(L, outbuf, outlen);
119 lua_State * uh_lua_init(const char *handler)
121 lua_State *L = lua_open();
123 const char *err_str = NULL;
125 /* Declare the Lua libraries we wish to use. */
126 /* Note: If you are opening and running a file containing Lua code */
127 /* using 'lua_dofile(l, "myfile.lua") - you must delcare all the libraries */
128 /* used in that file here also. */
129 static const luaL_reg lualibs[] =
131 { "base", luaopen_base },
132 { "string", luaopen_string },
136 /* preload libraries */
137 for (lib = lualibs; lib->func != NULL; lib++)
143 /* register global send and receive functions */
144 lua_pushcfunction(L, uh_lua_recv);
145 lua_setfield(L, LUA_GLOBALSINDEX, "recv");
147 lua_pushcfunction(L, uh_lua_send);
148 lua_setfield(L, LUA_GLOBALSINDEX, "send");
150 lua_pushcfunction(L, uh_lua_urldecode);
151 lua_setfield(L, LUA_GLOBALSINDEX, "urldecode");
154 /* load Lua handler */
155 switch( luaL_loadfile(L, handler) )
159 "Lua handler contains syntax errors, unable to continue\n");
164 "Lua handler ran out of memory, unable to continue\n");
169 "Lua cannot open the handler script, unable to continue\n");
173 /* compile Lua handler */
174 switch( lua_pcall(L, 0, 0, 0) )
177 err_str = luaL_checkstring(L, -1);
179 "Lua handler had runtime error, unable to continue\n"
180 "Error: %s\n", err_str
185 err_str = luaL_checkstring(L, -1);
187 "Lua handler ran out of memory, unable to continue\n"
188 "Error: %s\n", err_str
193 /* test handler function */
194 lua_getglobal(L, UH_LUA_CALLBACK);
196 if( ! lua_isfunction(L, -1) )
199 "Lua handler provides no " UH_LUA_CALLBACK "(), unable to continue\n");
213 void uh_lua_request(struct client *cl, struct http_request *req, lua_State *L)
217 const char *prefix = cl->server->conf->lua_prefix;
218 const char *err_str = NULL;
220 /* put handler callback on stack */
221 lua_getglobal(L, UH_LUA_CALLBACK);
224 /* build env table */
228 lua_pushlightuserdata(L, (void *)cl);
229 lua_setfield(L, -2, "client");
234 case UH_HTTP_MSG_GET:
235 lua_pushstring(L, "get");
238 case UH_HTTP_MSG_HEAD:
239 lua_pushstring(L, "head");
242 case UH_HTTP_MSG_POST:
243 lua_pushstring(L, "post");
247 lua_setfield(L, -2, "request_method");
250 lua_pushstring(L, req->url);
251 lua_setfield(L, -2, "request_url");
253 /* query string, path info */
254 if( (query_string = strchr(req->url, '?')) != NULL )
256 lua_pushstring(L, query_string + 1);
257 lua_setfield(L, -2, "query_string");
259 if( (int)(query_string - req->url) > strlen(prefix) )
262 &req->url[strlen(prefix)],
263 (int)(query_string - req->url) - strlen(prefix)
266 lua_setfield(L, -2, "path_info");
269 else if( strlen(req->url) > strlen(prefix) )
271 lua_pushstring(L, &req->url[strlen(prefix)]);
272 lua_setfield(L, -2, "path_info");
275 /* http protcol version */
276 lua_pushnumber(L, floor(req->version * 10) / 10);
277 lua_setfield(L, -2, "http_version");
280 /* address information */
281 lua_pushstring(L, sa_straddr(&cl->peeraddr));
282 lua_setfield(L, -2, "remote_addr");
284 lua_pushinteger(L, sa_port(&cl->peeraddr));
285 lua_setfield(L, -2, "remote_port");
287 lua_pushstring(L, sa_straddr(&cl->servaddr));
288 lua_setfield(L, -2, "server_addr");
290 lua_pushinteger(L, sa_port(&cl->servaddr));
291 lua_setfield(L, -2, "server_port");
297 foreach_header(i, req->headers)
299 lua_pushstring(L, req->headers[i+1]);
300 lua_setfield(L, -2, req->headers[i]);
303 lua_setfield(L, -2, "headers");
307 switch( lua_pcall(L, 1, 0, 0) )
310 err_str = luaL_checkstring(L, -1);
311 uh_http_sendhf(cl, 500, "Lua runtime error",
312 "Lua raised an error:\n%s\n", err_str);
316 err_str = luaL_checkstring(L, -1);
317 uh_http_sendhf(cl, 500, "Lua out of memory",
318 "Lua raised an error:\n%s\n", err_str);