add Lua scripting support to bozohttpd, see httpd(8) for details
This commit is contained in:
parent
6b629de220
commit
cb23152c39
@ -1,4 +1,4 @@
|
||||
# $NetBSD: Makefile,v 1.15 2013/10/12 07:49:40 mbalmer Exp $
|
||||
# $NetBSD: Makefile,v 1.16 2013/10/12 17:24:06 mbalmer Exp $
|
||||
#
|
||||
# $eterna: Makefile,v 1.30 2010/07/11 00:34:27 mrg Exp $
|
||||
#
|
||||
@ -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
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: bozohttpd.8,v 1.38 2013/07/11 08:19:56 wiz Exp $
|
||||
.\" $NetBSD: bozohttpd.8,v 1.39 2013/10/12 17:24:06 mbalmer Exp $
|
||||
.\"
|
||||
.\" $eterna: bozohttpd.8,v 1.101 2011/11/18 01:25:11 mrg Exp $
|
||||
.\"
|
||||
@ -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,27 @@ outside of the cgibin directory to be executed.
|
||||
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 three tables as arguments, the server
|
||||
environment, the request headers, and the decoded query string
|
||||
plus any data that was send as application/x-www-form-urlencoded.
|
||||
.It Fl c Ar cgibin
|
||||
Enables the CGI/1.1 interface.
|
||||
The
|
||||
@ -494,6 +516,10 @@ was written by Matthew R. Green
|
||||
The large list of contributors includes:
|
||||
.Bl -dash
|
||||
.It
|
||||
Marc Balmer
|
||||
.Aq mbalmer@NetBSD.org
|
||||
added Lua support for dynamic content creation
|
||||
.It
|
||||
Arnaud Lacombe
|
||||
.Aq alc@NetBSD.org
|
||||
provided some clean up for memory leaks
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: bozohttpd.c,v 1.42 2013/10/12 07:49:40 mbalmer Exp $ */
|
||||
/* $NetBSD: bozohttpd.c,v 1.43 2013/10/12 17:24:06 mbalmer Exp $ */
|
||||
|
||||
/* $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $ */
|
||||
|
||||
@ -1425,6 +1425,9 @@ transform_request(bozo_httpreq_t *request, int *isindex)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: bozohttpd.h,v 1.29 2013/10/12 07:49:40 mbalmer Exp $ */
|
||||
/* $NetBSD: bozohttpd.h,v 1.30 2013/10/12 17:24:07 mbalmer Exp $ */
|
||||
|
||||
/* $eterna: bozohttpd.h,v 1.39 2011/11/18 09:21:15 mrg Exp $ */
|
||||
|
||||
@ -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_t *, const char *, const char *);
|
||||
#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)
|
||||
|
437
libexec/httpd/lua-bozo.c
Normal file
437
libexec/httpd/lua-bozo.c
Normal file
@ -0,0 +1,437 @@
|
||||
/* $NetBSD: lua-bozo.c,v 1.1 2013/10/12 17:24:07 mbalmer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 Marc Balmer <marc@msys.ch>
|
||||
* 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
|
||||
|
||||
#define FORM "application/x-www-form-urlencoded"
|
||||
|
||||
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_read(lua_State *L)
|
||||
{
|
||||
bozohttpd_t *httpd;
|
||||
int len;
|
||||
char *data;
|
||||
|
||||
lua_pushstring(L, "bozohttpd");
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
httpd = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
len = luaL_checkinteger(L, -1);
|
||||
data = bozomalloc(httpd, len + 1);
|
||||
bozo_read(httpd, STDIN_FILENO, data, len);
|
||||
lua_pushstring(L, data);
|
||||
free(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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
|
||||
lua_write(lua_State *L)
|
||||
{
|
||||
bozohttpd_t *httpd;
|
||||
const char *data;
|
||||
|
||||
lua_pushstring(L, "bozohttpd");
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
httpd = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
data = luaL_checkstring(L, -1);
|
||||
lua_pushinteger(L, bozo_write(httpd, STDIN_FILENO, data, strlen(data)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
luaopen_httpd(lua_State *L)
|
||||
{
|
||||
struct luaL_Reg functions[] = {
|
||||
{ "flush", lua_flush },
|
||||
{ "print", lua_print },
|
||||
{ "read", lua_read },
|
||||
{ "register_handler", lua_register_handler },
|
||||
{ "write", lua_write },
|
||||
{ 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, 0, 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) || (type && *type
|
||||
&& !strcmp(type, FORM))) {
|
||||
lua_newtable(map->L);
|
||||
if (query && *query)
|
||||
lua_decode_query(map->L, query);
|
||||
if (type && *type && !strcmp(type, FORM)) {
|
||||
if (clen && *clen && atol(clen) > 0) {
|
||||
length = atol(clen);
|
||||
content = bozomalloc(httpd,
|
||||
length);
|
||||
bozo_read(httpd, STDIN_FILENO,
|
||||
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 */
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: main.c,v 1.5 2011/11/18 09:51:31 mrg Exp $ */
|
||||
/* $NetBSD: main.c,v 1.6 2013/10/12 17:24:07 mbalmer Exp $ */
|
||||
|
||||
/* $eterna: main.c,v 1.6 2011/11/18 09:21:15 mrg Exp $ */
|
||||
/* from: eterna: bozohttpd.c,v 1.159 2009/05/23 02:14:30 mrg Exp */
|
||||
@ -78,6 +78,9 @@ usage(bozohttpd_t *httpd, char *progname)
|
||||
#endif
|
||||
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
|
||||
@ -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,
|
||||
|
83
libexec/httpd/printenv.lua
Normal file
83
libexec/httpd/printenv.lua
Normal file
@ -0,0 +1,83 @@
|
||||
-- this small Lua script demonstrates the use of Lua in (bozo)httpd
|
||||
-- it will simply output the "environment"
|
||||
|
||||
-- Keep in mind that bozohttpd forks for each request when started in
|
||||
-- daemon mode, you can set global veriables here, but they will have
|
||||
-- the same value on each invocation. You can not keep state between
|
||||
-- two calls.
|
||||
|
||||
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
|
||||
|
||||
if count == nil then
|
||||
count = 1
|
||||
end
|
||||
|
||||
-- output a header
|
||||
print([[
|
||||
<html>
|
||||
<head>
|
||||
<title>Bozotic Lua Environment</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Bozotic Lua Environment</h1>
|
||||
]])
|
||||
|
||||
print('module version: ' .. httpd._VERSION .. '<br>')
|
||||
|
||||
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
|
||||
|
||||
if query ~= nil then
|
||||
print('<h2>Query Variables</h2>')
|
||||
for k, v in pairs(query) do
|
||||
print(k .. '=' .. v .. '<br/>')
|
||||
end
|
||||
end
|
||||
|
||||
print('<h2>Form Test</h2>')
|
||||
|
||||
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>')
|
||||
|
||||
if env.CONTENT_TYPE ~= nil then
|
||||
print('Content-type: ' .. env.CONTENT_TYPE .. '<br>')
|
||||
end
|
||||
|
||||
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)
|
Loading…
Reference in New Issue
Block a user