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