tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Dynamic content with bozohttpd
Am 12.10.13 11:55, schrieb Jochen Kunz:
> On Fri, 11 Oct 2013 22:40:34 +0200
> Marc Balmer <marc%msys.ch@localhost> wrote:
>
>> There is a Lua binding to gpio(4) in src/lib/lua/gpio.
> I know. This brought up the idea.
>
>> I think it could be '3lua'.
> So do I.
wiz decided (on my reqeust) that 3lua will be used.
>
>>> How to get POST data from within a Lua handler?
>> I did not try. But reading CONTENT_LENGTH bytes should do it.
> If this still works when bozohttpd is running in daemon mode, without
> inetd(8).
Apparently it does, see below...
>
>>> What about PATH_INFO when GETing
>>> http://<hostname>/rest/printenv/foo/bar
>> That could be added.
> Maybe have a look at the APIs of other small CGI libs like cgic (C) and
> cgicc (C++) to get some inspiration.
>
Actually it works... See the attached third version of my diff, I added
functions to decode the query string _and_ form data, these are passed
in a third table to the Lua function.
I am myself surprised that it works... ;)
- Marx
Index: libexec/httpd/Makefile
===================================================================
RCS file: /cvsroot/src/libexec/httpd/Makefile,v
retrieving revision 1.15
diff -u -p -r1.15 Makefile
--- libexec/httpd/Makefile 12 Oct 2013 07:49:40 -0000 1.15
+++ libexec/httpd/Makefile 12 Oct 2013 10:11:55 -0000
@@ -13,6 +13,7 @@
# NO_DYNAMIC_CONTENT /* don't support dynamic content updates */
# NO_SSL_SUPPORT /* don't support ssl (https) */
# DO_HTPASSWD /* support .htpasswd files */
+# NO_LUA_SUPPORT /* don't support Lua for dynamic content */
#
# these are usually set via the "COPTS" variable, or some other method
# for setting CFLAGS relevant to your make, eg
@@ -23,10 +24,10 @@ PROG= httpd
MAN= httpd.8
BUILDSYMLINKS+=bozohttpd.8 httpd.8
SRCS= bozohttpd.c ssl-bozo.c auth-bozo.c cgi-bozo.c daemon-bozo.c \
- tilde-luzah-bozo.c dir-index-bozo.c content-bozo.c
+ tilde-luzah-bozo.c dir-index-bozo.c content-bozo.c lua-bozo.c
SRCS+= main.c
-LDADD= -lcrypt
+LDADD= -lcrypt -llua
DPADD= ${LIBCRYPT}
WARNS?= 4
Index: libexec/httpd/bozohttpd.8
===================================================================
RCS file: /cvsroot/src/libexec/httpd/bozohttpd.8,v
retrieving revision 1.38
diff -u -p -r1.38 bozohttpd.8
--- libexec/httpd/bozohttpd.8 11 Jul 2013 08:19:56 -0000 1.38
+++ libexec/httpd/bozohttpd.8 12 Oct 2013 10:11:56 -0000
@@ -26,7 +26,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd June 11, 2013
+.Dd October 12, 2013
.Dt HTTPD 8
.Os
.Sh NAME
@@ -36,6 +36,7 @@
.Nm
.Op Fl CIMPSZciptvx
.Op Fl C Ar suffix cgihandler
+.Op Fl L Ar prefix script
.Op Fl I Ar port
.Op Fl M Ar suffix type encoding encoding11
.Op Fl P Ar pidfile
@@ -95,6 +96,26 @@ outside of the cgibin directory to be ex
Multiple
.Fl C
options may be passed.
+.It Fl L Ar prefix script
+Adds a new Lua script for a particular prefix.
+The
+.Ar prefix
+should be an arbitrary text, and the
+.Ar script
+should be a full path to a Lua script.
+Multiple
+.Fl L
+options may be passed.
+A separate Lua state is created for each prefix.
+The Lua script can register callbacks using the
+httpd.register_handler('<name>', function) Lua function,
+which will trigger the execution of the Lua function
+.Em function
+when a URL in the form
+.Em http://<hostname>/<prefix>/<name>
+is being accessed.
+The function is passed two tables as arguments, the server
+environment and the request headers.
.It Fl c Ar cgibin
Enables the CGI/1.1 interface.
The
@@ -494,6 +515,10 @@ was written by Matthew R. Green
The large list of contributors includes:
.Bl -dash
.It
+Marc Balmer
+.Aq mbalmer%NetBSD.org@localhost
+added Lua support for dynamic content creation
+.It
Arnaud Lacombe
.Aq alc%NetBSD.org@localhost
provided some clean up for memory leaks
Index: libexec/httpd/bozohttpd.c
===================================================================
RCS file: /cvsroot/src/libexec/httpd/bozohttpd.c,v
retrieving revision 1.42
diff -u -p -r1.42 bozohttpd.c
--- libexec/httpd/bozohttpd.c 12 Oct 2013 07:49:40 -0000 1.42
+++ libexec/httpd/bozohttpd.c 12 Oct 2013 10:11:57 -0000
@@ -1425,6 +1425,9 @@ transform_request(bozo_httpreq_t *reques
if (bozo_process_cgi(request))
return 0;
+ if (bozo_process_lua(request))
+ return 0;
+
debug((httpd, DEBUG_FAT, "transform_request set: %s", newfile));
return 1;
bad_done:
@@ -2086,6 +2089,9 @@ bozo_init_httpd(bozohttpd_t *httpd)
"bozohttpd: memory_allocation failure\n");
return 0;
}
+#ifndef NO_LUA_SUPPORT
+ SIMPLEQ_INIT(&httpd->lua_states);
+#endif
return 1;
}
Index: libexec/httpd/bozohttpd.h
===================================================================
RCS file: /cvsroot/src/libexec/httpd/bozohttpd.h,v
retrieving revision 1.29
diff -u -p -r1.29 bozohttpd.h
--- libexec/httpd/bozohttpd.h 12 Oct 2013 07:49:40 -0000 1.29
+++ libexec/httpd/bozohttpd.h 12 Oct 2013 10:11:57 -0000
@@ -36,6 +36,9 @@
#include <sys/stat.h>
+#ifndef NO_LUA_SUPPORT
+#include <lua.h>
+#endif
#include <stdio.h>
/* lots of "const" but gets free()'ed etc at times, sigh */
@@ -47,6 +50,22 @@ typedef struct bozoheaders {
SIMPLEQ_ENTRY(bozoheaders) h_next;
} bozoheaders_t;
+#ifndef NO_LUA_SUPPORT
+typedef struct lua_handler {
+ const char *name;
+ int ref;
+ SIMPLEQ_ENTRY(lua_handler) h_next;
+} lua_handler_t;
+
+typedef struct lua_state_map {
+ const char *script;
+ const char *prefix;
+ lua_State *L;
+ SIMPLEQ_HEAD(, lua_handler) handlers;
+ SIMPLEQ_ENTRY(lua_state_map) s_next;
+} lua_state_map_t;
+#endif
+
typedef struct bozo_content_map_t {
const char *name; /* postfix of file */
size_t namelen; /* length of postfix */
@@ -94,6 +113,10 @@ typedef struct bozohttpd_t {
int hide_dots; /* hide .* */
int process_cgi; /* use the cgi handler */
char *cgibin; /* cgi-bin directory */
+#ifndef NO_LUA_SUPPORT
+ int process_lua; /* use the Lua handler */
+ SIMPLEQ_HEAD(, lua_state_map) lua_states;
+#endif
void *sslinfo; /* pointer to ssl struct */
int dynamic_content_map_size;/* size of dyn cont map */
bozo_content_map_t *dynamic_content_map;/* dynamic content map */
@@ -252,6 +275,15 @@ void bozo_add_content_map_cgi(bozohttpd_
#endif /* NO_CGIBIN_SUPPORT */
+/* lua-bozo.c */
+#ifdef NO_LUA_SUPPORT
+#define bozo_process_lua(h) 0
+#else
+void bozo_add_lua_map(bozohttpd_t *, const char *, const char *);
+int bozo_process_lua(bozo_httpreq_t *);
+#endif /* NO_LUA_SUPPORT */
+
+
/* daemon-bozo.c */
#ifdef NO_DAEMON_MODE
#define bozo_daemon_init(x) do { /* nothing */ }
while (0)
Index: libexec/httpd/lua-bozo.c
===================================================================
RCS file: libexec/httpd/lua-bozo.c
diff -N libexec/httpd/lua-bozo.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libexec/httpd/lua-bozo.c 12 Oct 2013 10:11:58 -0000
@@ -0,0 +1,391 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 2013 Marc Balmer <marc%msys.ch@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer and
+ * dedication in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/* this code implements dynamic content generation using Lua for bozohttpd */
+
+#ifndef NO_LUA_SUPPORT
+
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "bozohttpd.h"
+
+/* Lua binding for bozohttp */
+
+#if LUA_VERSION_NUM < 502
+#define LUA_HTTPDLIBNAME "httpd"
+#endif
+
+static int
+lua_flush(lua_State *L)
+{
+ bozohttpd_t *httpd;
+
+ lua_pushstring(L, "bozohttpd");
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ httpd = lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ bozo_flush(httpd, stdout);
+ return 0;
+}
+
+static int
+lua_print(lua_State *L)
+{
+ bozohttpd_t *httpd;
+
+ lua_pushstring(L, "bozohttpd");
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ httpd = lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ bozo_printf(httpd, "%s\r\n", lua_tostring(L, -1));
+ return 0;
+}
+
+static int
+lua_register_handler(lua_State *L)
+{
+ lua_state_map_t *map;
+ lua_handler_t *handler;
+ bozohttpd_t *httpd;
+
+ lua_pushstring(L, "lua_state_map");
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ map = lua_touserdata(L, -1);
+ lua_pushstring(L, "bozohttpd");
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ httpd = lua_touserdata(L, -1);
+ lua_pop(L, 2);
+
+ luaL_checkstring(L, 1);
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ handler = bozomalloc(httpd, sizeof(lua_handler_t));
+
+ handler->name = bozostrdup(httpd, lua_tostring(L, 1));
+ handler->ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ SIMPLEQ_INSERT_TAIL(&map->handlers, handler, h_next);
+ httpd->process_lua = 1;
+ return 0;
+}
+
+static int
+luaopen_httpd(lua_State *L)
+{
+ struct luaL_Reg functions[] = {
+ { "flush", lua_flush },
+ { "print", lua_print },
+ { "register_handler", lua_register_handler },
+ { NULL, NULL }
+ };
+#if LUA_VERSION_NUM >= 502
+ luaL_newlib(L, functions);
+#else
+ luaL_register(L, LUA_HTTPDLIBNAME, functions);
+#endif
+ lua_pushstring(L, "httpd 1.0.0");
+ lua_setfield(L, -2, "_VERSION");
+ return 1;
+}
+
+#if LUA_VERSION_NUM < 502
+static void
+lua_openlib(lua_State *L, const char *name, lua_CFunction fn)
+{
+ lua_pushcfunction(L, fn);
+ lua_pushstring(L, name);
+ lua_call(L, 1, 0);
+}
+#endif
+
+/* bozohttpd integration */
+void
+bozo_add_lua_map(bozohttpd_t *httpd, const char *prefix, const char *script)
+{
+ lua_state_map_t *map;
+ char *cwd, *path;
+
+ map = bozomalloc(httpd, sizeof(lua_state_map_t));
+ map->prefix = bozostrdup(httpd, prefix);
+ if (*script == '/')
+ map->script = bozostrdup(httpd, script);
+ else {
+ cwd = getwd(NULL);
+ asprintf(&path, "%s/%s", cwd, script);
+ map->script = path;
+ free(cwd);
+ }
+ map->L = luaL_newstate();
+ if (map->L == NULL)
+ bozo_err(httpd, 1, "can't create Lua state");
+ SIMPLEQ_INIT(&map->handlers);
+
+#if LUA_VERSION_NUM >= 502
+ luaL_openlibs(map->L);
+ lua_getglobal(L, "package");
+ lua_getfield(L, -1, "preload");
+ lua_pushcfunction(L, luaopen_httpd);
+ lua_setfield(L, -2, "httpd");
+ lua_pop(L, 2);
+#else
+ lua_openlib(map->L, "", luaopen_base);
+ lua_openlib(map->L, LUA_LOADLIBNAME, luaopen_package);
+ lua_openlib(map->L, LUA_TABLIBNAME, luaopen_table);
+ lua_openlib(map->L, LUA_STRLIBNAME, luaopen_string);
+ lua_openlib(map->L, LUA_MATHLIBNAME, luaopen_math);
+ lua_openlib(map->L, LUA_OSLIBNAME, luaopen_os);
+ lua_openlib(map->L, LUA_IOLIBNAME, luaopen_io);
+ lua_openlib(map->L, LUA_HTTPDLIBNAME, luaopen_httpd);
+#endif
+ lua_pushstring(map->L, "lua_state_map");
+ lua_pushlightuserdata(map->L, map);
+ lua_settable(map->L, LUA_REGISTRYINDEX);
+
+ lua_pushstring(map->L, "bozohttpd");
+ lua_pushlightuserdata(map->L, httpd);
+ lua_settable(map->L, LUA_REGISTRYINDEX);
+
+ if (luaL_loadfile(map->L, script))
+ bozo_err(httpd, 1, "failed to load script %s: %s", script,
+ lua_tostring(map->L, -1));
+ if (lua_pcall(map->L, 0, LUA_MULTRET, 0))
+ bozo_err(httpd, 1, "failed to execute script %s: %s", script,
+ lua_tostring(map->L, -1));
+ SIMPLEQ_INSERT_TAIL(&httpd->lua_states, map, s_next);
+}
+
+static void
+lua_env(lua_State *L, const char *name, const char *value)
+{
+ lua_pushstring(L, value);
+ lua_setfield(L, -2, name);
+}
+
+/* decode query string */
+static void
+lua_url_decode(lua_State *L, char *s)
+{
+ char *v, *p, *val, *q;
+ char buf[3];
+ int c;
+
+ v = strchr(s, '=');
+ if (v == NULL)
+ return;
+ *v++ = '\0';
+ val = malloc(strlen(v) + 1);
+ if (val == NULL)
+ return;
+
+ for (p = v, q = val; *p; p++) {
+ switch (*p) {
+ case '%':
+ if (*(p + 1) == '\0' || *(p + 2) == '\0')
+ return;
+ buf[0] = *++p;
+ buf[1] = *++p;
+ buf[2] = '\0';
+ sscanf(buf, "%2x", &c);
+ *q++ = (char)c;
+ break;
+ case '+':
+ *q++ = ' ';
+ break;
+ default:
+ *q++ = *p;
+ }
+ }
+ lua_pushstring(L, val);
+ lua_setfield(L, -2, s);
+ free(val);
+}
+
+static void
+lua_decode_query(lua_State *L, char *query)
+{
+ char *s;
+
+ s = strtok(query, "&");
+ while (s) {
+ lua_url_decode(L, s);
+ s = strtok(NULL, "&");
+ }
+}
+
+int
+bozo_process_lua(bozo_httpreq_t *request)
+{
+ bozohttpd_t *httpd = request->hr_httpd;
+ lua_state_map_t *map;
+ lua_handler_t *hndlr;
+ int ret, length;
+ char date[40];
+ bozoheaders_t *headp;
+ char *s, *query, *uri, *file, *command, *info, *content;
+ const char *type, *clen;
+ char *prefix, *handler, *p;
+
+ if (!httpd->process_lua)
+ return 0;
+
+ uri = request->hr_oldfile ? request->hr_oldfile : request->hr_file;
+
+ if (*uri == '/') {
+ file = bozostrdup(httpd, uri);
+ prefix = bozostrdup(httpd, &uri[1]);
+ } else {
+ prefix = bozostrdup(httpd, uri);
+ asprintf(&file, "/%s", uri);
+ }
+ if (file == NULL) {
+ free(prefix);
+ return 0;
+ }
+
+ if (request->hr_query && strlen(request->hr_query))
+ query = bozostrdup(httpd, request->hr_query);
+ else
+ query = NULL;
+
+ p = strchr(prefix, '/');
+ if (p == NULL){
+ free(prefix);
+ return 0;
+ }
+ *p++ = '\0';
+ handler = p;
+ if (!*handler) {
+ free(prefix);
+ return 0;
+ }
+ p = strchr(handler, '/');
+ if (p != NULL)
+ *p++ = '\0';
+
+ info = NULL;
+ command = file + 1;
+ if ((s = strchr(command, '/')) != NULL) {
+ info = bozostrdup(httpd, s);
+ *s = '\0';
+ }
+
+ type = request->hr_content_type;
+ clen = request->hr_content_length;
+
+ SIMPLEQ_FOREACH(map, &httpd->lua_states, s_next) {
+ if (strcmp(map->prefix, prefix))
+ continue;
+
+ SIMPLEQ_FOREACH(hndlr, &map->handlers, h_next) {
+ if (strcmp(hndlr->name, handler))
+ continue;
+
+ lua_rawgeti(map->L, LUA_REGISTRYINDEX, hndlr->ref);
+
+ /* Create the "environment" */
+ lua_newtable(map->L);
+ lua_env(map->L, "SERVER_NAME",
+ BOZOHOST(httpd, request));
+ lua_env(map->L, "GATEWAY_INTERFACE", "Luigi/1.0");
+ lua_env(map->L, "SERVER_PROTOCOL", request->hr_proto);
+ lua_env(map->L, "REQUEST_METHOD",
+ request->hr_methodstr);
+ lua_env(map->L, "SCRIPT_PREFIX", map->prefix);
+ lua_env(map->L, "SCRIPT_NAME", file);
+ lua_env(map->L, "HANDLER_NAME", hndlr->name);
+ lua_env(map->L, "SCRIPT_FILENAME", map->script);
+ lua_env(map->L, "SERVER_SOFTWARE",
+ httpd->server_software);
+ lua_env(map->L, "REQUEST_URI", uri);
+ lua_env(map->L, "DATE_GMT",
+ bozo_http_date(date, sizeof(date)));
+ if (query && *query)
+ lua_env(map->L, "QUERY_STRING", query);
+ if (info && *info)
+ lua_env(map->L, "PATH_INFO", info);
+ if (type && *type)
+ lua_env(map->L, "CONTENT_TYPE", type);
+ if (clen && *clen)
+ lua_env(map->L, "CONTENT_LENGTH", clen);
+ if (request->hr_serverport && *request->hr_serverport)
+ lua_env(map->L, "SERVER_PORT",
+ request->hr_serverport);
+ if (request->hr_remotehost && *request->hr_remotehost)
+ lua_env(map->L, "REMOTE_HOST",
+ request->hr_remotehost);
+ if (request->hr_remoteaddr && *request->hr_remoteaddr)
+ lua_env(map->L, "REMOTE_ADDR",
+ request->hr_remoteaddr);
+
+ /* Pass the headers in a separate table */
+ lua_newtable(map->L);
+ SIMPLEQ_FOREACH(headp, &request->hr_headers, h_next)
+ lua_env(map->L, headp->h_header,
+ headp->h_value);
+
+ /* Pass the query variables */
+ if ((query && *query) || (clen && *clen)) {
+ lua_newtable(map->L);
+ if (query && *query)
+ lua_decode_query(map->L, query);
+ if (clen && *clen) {
+ length = atol(clen);
+ content = bozomalloc(httpd, length);
+ read(0, content, length);
+ lua_decode_query(map->L, content);
+ free(content);
+ }
+ } else
+ lua_pushnil(map->L);
+
+ ret = lua_pcall(map->L, 3, 0, 0);
+ if (ret)
+ printf("<br>Lua error: %s\n",
+ lua_tostring(map->L, -1));
+ bozo_flush(httpd, stdout);
+ free(prefix);
+ free(uri);
+ free(info);
+ return 1;
+ }
+ }
+ free(prefix);
+ free(uri);
+ free(info);
+ return 0;
+}
+
+#endif /* NO_LUA_SUPPORT */
Index: libexec/httpd/main.c
===================================================================
RCS file: /cvsroot/src/libexec/httpd/main.c,v
retrieving revision 1.5
diff -u -p -r1.5 main.c
--- libexec/httpd/main.c 18 Nov 2011 09:51:31 -0000 1.5
+++ libexec/httpd/main.c 12 Oct 2013 10:11:58 -0000
@@ -79,6 +79,9 @@ usage(bozohttpd_t *httpd, char *progname
bozo_warn(httpd,
" -c cgibin\t\tenable cgi-bin support in this directory");
#endif
+#ifndef NO_LUA_SUPPORT
+ bozo_warn(httpd, " -L arg script\tadd this Lua script");
+#endif
bozo_warn(httpd, " -I port\t\tbind or use on this port");
#ifndef NO_DAEMON_MODE
bozo_warn(httpd, " -b\t\t\tbackground and go into daemon mode");
@@ -138,9 +141,22 @@ main(int argc, char **argv)
bozo_set_defaults(&httpd, &prefs);
while ((c = getopt(argc, argv,
- "C:HI:M:P:S:U:VXZ:bc:defhi:np:rst:uv:x:z:")) != -1) {
+ "C:HI:L:M:P:S:U:VXZ:bc:defhi:np:rst:uv:x:z:")) != -1) {
switch(c) {
+ case 'L':
+#ifdef NO_LUA_SUPPORT
+ bozo_err(&httpd, 1,
+ "Lua support is not enabled");
+ /* NOTREACHED */
+#else
+ /* make sure there's two argument */
+ if (argc - optind < 1)
+ usage(&httpd, progname);
+ bozo_add_lua_map(&httpd, optarg, argv[optind]);
+ optind++;
+ break;
+#endif /* NO_LUA_SUPPORT */
case 'M':
#ifdef NO_DYNAMIC_CONTENT
bozo_err(&httpd, 1,
Index: libexec/httpd/printenv.lua
===================================================================
RCS file: libexec/httpd/printenv.lua
diff -N libexec/httpd/printenv.lua
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libexec/httpd/printenv.lua 12 Oct 2013 10:11:58 -0000
@@ -0,0 +1,65 @@
+-- this small Lua script demonstrates the use of Lua in (bozo)httpd
+-- it will simply output the "environment"
+
+local httpd = require 'httpd'
+
+function printenv(env, headers, query)
+
+ -- we get the "environment" in the env table, the values are more
+ -- or less the same as the variable for a CGI program
+
+ -- output a header
+ print([[
+ <html>
+ <head>
+ <title>Bozotic Lua Environment</title>
+ </head>
+ <body>
+ <h1>Bozotic Lua Environment</h1>
+ ]])
+
+ print('module version: ' .. httpd._VERSION)
+
+ print('<h2>Server Environment</h2>')
+ -- print the list of "environment" variables
+ for k, v in pairs(env) do
+ print(k .. '=' .. v .. '<br/>')
+ end
+
+ print('<h2>Request Headers</h2>')
+ for k, v in pairs(headers) do
+ print(k .. '=' .. v .. '<br/>')
+ end
+
+ print('<h2>Query Variables</h2>')
+ for k, v in pairs(query) do
+ print(k .. '=' .. v .. '<br/>')
+ end
+
+ print([[
+ <form method="POST" action="/rest/form?sender=me">
+ <input type="text" name="a_value">
+ <input type="submit">
+ </form>
+ ]])
+ -- output a footer
+ print([[
+ </body>
+ </html>
+ ]])
+end
+
+function form(env, header, query)
+ if query ~= nil then
+ print('<h2>Form Variables</h2>')
+ for k, v in pairs(query) do
+ print(k .. '=' .. v .. '<br/>')
+ end
+ else
+ print('No values')
+ end
+end
+
+-- register this handler for http://<hostname>/<prefix>/printenv
+httpd.register_handler('printenv', printenv)
+httpd.register_handler('form', form)
Home |
Main Index |
Thread Index |
Old Index