Installation
Refer to the following blog post to install thttpd software
http://blog.csdn.net/21aspnet/article/details/7045845
http://blog.csdn.net/dragoncheng/article/details/5614559
THTTPD configuration file:
[Email protected]:/usr/local/bin# cat/usr/local/thttpd/
conf/etc/logs/man/sbin/www/
[Email protected]:/usr/local/bin# cat/usr/local/thttpd/conf/thttpd.conf
Port=80
User=www
host=0.0.0.0
Logfile=/usr/local/thttpd/logs/thttpd.log
Pidfile=/usr/local/thttpd/logs/thttpd.pid
#throttles =/usr/local/thttpd/etc/throttle.conf
#urlpat =*.txt|*.mp3
#charset =utf-8
Dir=/usr/local/thttpd/www
cgipat=/cgi-bin/*
The Cgilua is installed with Luarocks. It relies on WSAPI to run.
CGILUA.CGI Launcher:
[Email protected]:/usr/local/bin# cat cgilua.cgi
#!/bin/sh
exec '/usr/bin/lua5.1 '-e ' package.path= '/root/.luarocks/share/lua/5.1/? Lua;/root/.luarocks/share/lua/5.1/?/init.lua;/usr/local/share/lua/5.1/?. Lua;/usr/local/share/lua/5.1/?/init.lua; ". Package.path; Package.cpath= "/ROOT/.LUAROCKS/LIB/LUA/5.1/?" So;/usr/local/lib/lua/5.1/?. So; ". Package.cpath '-e ' local k,l,_=pcall (Require, "Luarocks.loader") _=k and L.add_context ("Cgilua", "5.1.4-2") '/usr/ local/lib/luarocks/rocks/cgilua/5.1.4-2/bin/cgilua.cgi ' "[email protected]"
[Email protected]:/usr/local/bin#
[Email protected]:/usr/local/bin#
[Email protected]:/usr/local/bin# cat/usr/local/lib/luarocks/rocks/cgilua/5.1.4-2/bin/cgilua.cgi
#!/usr/bin/env Lua
--Cgilua (SAPI) launcher, extracts script to launch
--either from the command line (with #!cgilua in the script)
--or from script_filename/path_translated
Pcall (Require, "Luarocks.require")
Local common = require "Wsapi.common"
Local CGI = require "wsapi.cgi"
Local SAPI = require "Wsapi.sapi"
Local Arg_filename = (...)
Local function Sapi_loader (wsapi_env)
Common.normalize_paths (wsapi_env, Arg_filename, "cgilua.cgi")
Return Sapi.run (wsapi_env)
End
Cgi.run (Sapi_loader)
[Email protected]:/usr/local/bin#
Process Analysis THTTPD configuration encounters a request for a Cgipat rule, the CGI program is started
The Cgipat rule is
cgipat=/cgi-bin/*
That is, the URL contains a file name request beginning with/cgi-bin/.
Corresponds to the start CGI subroutine code in the THTTPD:
/* It world-executable and in the CGI area? */
if (Hc->hs->cgi_pattern! = (char*) 0 &&
(Hc->sb.st_mode & S_ixoth) &&
Match (Hc->hs->cgi_pattern, hc->expnfilename))
return CGI (HC);
Start CGI program logic
In the CGI function, the fork is actually a sub-process
R = Fork ();
if (R < 0)
{
Syslog (Log_err, "fork-%m");
Httpd_send_err (
HC, $, Err500title, "", Err500form, Hc->encodedurl);
return-1;
}
if (r = = 0)
{
/* Child process. */
sub_process = 1;
Httpd_unlisten (HC->HS);
Cgi_child (HC);
}
Cgi_child continue to execute logic for child processes
1. Prepare environment variables:
/* Make the environment vector. */
ENVP = MAKE_ENVP (hc);
/* make the argument vector. */
ARGP = MAKE_ARGP (hc);
Environment variables, including several CGI parameters:
Static char**
MAKE_ENVP (httpd_conn* HC)
{
Static char* envp[50];
int ENVN;
char* CP;
Char buf[256];
ENVN = 0;
envp[envn++] = build_env ("path=%s", Cgi_path);
#ifdef Cgi_ld_library_path
envp[envn++] = build_env ("ld_library_path=%s", Cgi_ld_library_path);
#endif/* Cgi_ld_library_path */
envp[envn++] = build_env ("server_software=%s", server_software);
if (hc->hs->vhost && hc->hostname! = (char*) 0 && hc->hostname[0]! = '% ')
CP = hc->hostname;
else if (hc->hdrhost! = (char*) 0 && hc->hdrhost[0]! = ' + ')
CP = hc->hdrhost;
else if (hc->reqhost! = (char*) 0 && hc->reqhost[0]! = ' + ')
CP = hc->reqhost;
Else
CP = hc->hs->server_hostname;
if (cp! = (char*) 0)
envp[envn++] = build_env ("server_name=%s", CP);
envp[envn++] = "gateway_interface=cgi/1.1";
envp[envn++] = build_env ("server_protocol=%s", Hc->protocol);
(void) my_snprintf (buf, sizeof (BUF), "%d", (int) hc->hs->port);
envp[envn++] = build_env ("server_port=%s", buf);
envp[envn++] = build_env (
"request_method=%s", Httpd_method_str (Hc->method));
if (hc->pathinfo[0]! = ' + ')
{
char* CP2;
size_t l;
envp[envn++] = build_env ("path_info=/%s", hc->pathinfo);
L = strlen (HC->HS->CWD) + strlen (hc->pathinfo) + 1;
CP2 = NEW (char, L);
if (cp2! = (char*) 0)
{
(void) my_snprintf (CP2, L, "%s%s", HC->HS->CWD, Hc->pathinfo);
envp[envn++] = build_env ("path_translated=%s", CP2);
}
}
envp[envn++] = build_env (
"script_name=/%s", strcmp (Hc->origfilename, ".") = = 0?
"": hc->origfilename);
if (hc->query[0]! = ' + ')
envp[envn++] = build_env ("query_string=%s", hc->query);
envp[envn++] = build_env (
"remote_addr=%s", Httpd_ntoa (&HC->CLIENT_ADDR));
if (hc->referrer[0]! = ' + ')
{
envp[envn++] = build_env ("http_referer=%s", hc->referrer);
envp[envn++] = build_env ("http_referrer=%s", hc->referrer);
}
if (hc->useragent[0]! = ' + ')
envp[envn++] = build_env ("http_user_agent=%s", hc->useragent);
if (hc->accept[0]! = ' + ')
envp[envn++] = build_env ("http_accept=%s", hc->accept);
if (hc->accepte[0]! = ' + ')
envp[envn++] = build_env ("http_accept_encoding=%s", hc->accepte);
if (hc->acceptl[0]! = ' + ')
envp[envn++] = build_env ("http_accept_language=%s", HC->ACCEPTL);
if (hc->cookie[0]! = ' + ')
envp[envn++] = build_env ("http_cookie=%s", Hc->cookie);
if (hc->contenttype[0]! = ' + ')
envp[envn++] = build_env ("content_type=%s", Hc->contenttype);
if (hc->hdrhost[0]! = ' + ')
envp[envn++] = build_env ("http_host=%s", hc->hdrhost);
if (hc->contentlength! =-1)
{
(void) my_snprintf (
BUF, sizeof (BUF), "%lu", (unsigned long) hc->contentlength);
envp[envn++] = build_env ("content_length=%s", buf);
}
if (hc->remoteuser[0]! = ' + ')
envp[envn++] = build_env ("remote_user=%s", Hc->remoteuser);
if (hc->authorization[0]! = ' + ')
envp[envn++] = build_env ("auth_type=%s", "Basic");
/* We only have support for Basic auth at the moment. */
if (getenv ("TZ")! = (char*) 0)
envp[envn++] = build_env ("tz=%s", getenv ("TZ"));
envp[envn++] = build_env ("cgi_pattern=%s", Hc->hs->cgi_pattern);
ENVP[ENVN] = (char*) 0;
return ENVP;
}
2. Set the connection FD to the standard input of the CGI program:
/* Otherwise, the request socket is stdin. */
if (hc->conn_fd! = Stdin_fileno)
(void) dup2 (hc->conn_fd, Stdin_fileno);
3. Set the connection FD to the standard output and error of the CGI program:
/* Otherwise, the request socket is stdout/stderr. */
if (hc->conn_fd! = Stdout_fileno)
(void) dup2 (hc->conn_fd, Stdout_fileno);
if (hc->conn_fd! = Stderr_fileno)
(void) dup2 (hc->conn_fd, Stderr_fileno);
4. Start the CGI business process to replace the current fork image
/* Run the program. */
(void) Execve (binary, ARGP, ENVP);
Note that environment variables have been injected into the startup process, that is, in the business process, you can access the CGI parameters.
Include current script name: Script_name
Execv function
The exec () family of functions replaces the current process image with a new process image. The functions described in this manual page is front-ends for Execve (2). (See the
Manual page for Execve (2) for further details on the replacement of the current process image.)
Http://www.tutorialspoint.com/unix_system_calls/execve.htm
Execve () Executes the program pointed to by filename. filename must is either a binary executable, or a script starting with a line of the form "#! Interpreter [Arg] ". In the latter case, the interpreter must was a valid pathname for an executable which was not itself a script, which would be Invoked as interpreter [arg] filename.
If the file to be executed is a script, start the interpreter program for the script script and execute the script.
Script Content
This script in the Z:\CGILUA-MASTER\CGILUA-MASTER\EXAMPLES\INDEX.LP example
To start the program env, execute the CGILUA.CGI program to process the script file
#!/usr/bin/env cgilua.cgi
<! DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 strict//en"
"Http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
<title>welcome to Kepler!</title>
<link rel= "stylesheet" href= "Css/doc.css" type= "Text/css"/>
<meta http-equiv= "Content-type" content= "text/html; Charset=utf-8 "/>
<body>
The role of the ENV command program, you can see here is specifically used to start the command (cgilua.cgi), and does not set the environment variable
NAME
Env-run a program in a modified environment
Synopsis
env [OPTION] ... [-] [Name=value] ... [COMMAND [ARG] ...]
DESCRIPTION
Set each NAME to VALUE in the environment and run COMMAND.
Mandatory arguments to long options is Mandatory for short options too.
cgilua.cgi
CGILUA.CGI main business documents for/USR/LOCAL/LIB/LUAROCKS/ROCKS/CGILUA/5.1.4-2/BIN/CGILUA.CGI
dependent on wsapi.cgi and Wsapi.common and wsapi.cgi modules
[Email protected]:/usr/local/bin# cat cgilua.cgi
#!/bin/sh
Exec '/usr/bin/lua5.1 '-e ' package.path= "/ROOT/.LUAROCKS/SHARE/LUA/5.1/?. Lua;/root/.luarocks/share/lua/5.1/?/init.lua;/usr/local/share/lua/5.1/?. Lua;/usr/local/share/lua/5.1/?/init.lua; ". Package.path; Package.cpath= "/ROOT/.LUAROCKS/LIB/LUA/5.1/?" So;/usr/local/lib/lua/5.1/?. So; ". Package.cpath '-e ' local k,l,_=pcall (Require, "Luarocks.loader") _=k and L.add_context ("Cgilua", "5.1.4-2") '/usr/ Local/lib/luarocks/rocks/cgilua/5.1.4-2/bin/cgilua.cgi ' "[email protected]"
[email protected]:/usr /local/bin#
[email protected]:/usr/local/bin#
[email protected]:/usr/local/bin#
[email] protected]:/usr/local/bin# cat/usr/local/lib/luarocks/rocks/cgilua/5.1.4-2/bin/cgilua.cgi
#!/usr/bin/ Env LUA
--Cgilua (SAPI) launcher, extracts script to launch
--either from the command line (with #!cgilua in the script)
--or from script_filename/path_translated
Pcall (Require, "Luarocks.require")
Local common = require "Wsapi.common"
Local CGI = require "wsapi.cgi"
Local SAPI = require "Wsapi.sapi"
Local Arg_filename = (...)
Local function Sapi_loader (wsapi_env)
Common.normalize_paths (wsapi_env, Arg_filename, "cgilua.cgi")
Return Sapi.run (wsapi_env)
End
Cgi.run (Sapi_loader)
[email protected]:/usr/local/bin#
1, the wsapi.cgi module is the script portal, which provides a channel to get environment variables, set to the Wsapi_env table:
And will say in the previous article, CGI program will connect FD, take over, as standard input and output as well as the wrong representative.
Local OS = require "OS"
Local IO = require "IO"
Local common = require "Wsapi.common"
Common.setmode ()
Local _m = {}
--Runs An WSAPI application for this CGI request
function _m.run (App_run)
Common.run (app_run, {input = Io.stdin, output = Io.stdout,
Error = Io.stderr, env = os.getenv })
End
Return _m
2, Wsapi.sapi script implementation, start the logic of Cgilua execution:
Local response = require "Wsapi.response"
Local _m = {}
function _m.run (wsapi_env)
_g.cgilua_apps = _g.cgilua_apps or wsapi_env. Document_root. "/cgilua"
_g.cgilua_conf = _g.cgilua_conf or wsapi_env. Document_root. "/cgilua"
_g.cgilua_tmp = _g.cgilua_tmp or os.getenv ("tmp") or os.getenv ("TEMP") or "/tmp"
_g.cgilua_isdirect = True
Local res = Response.new ()
_g.sapi = {
Info = {
_copyright = "COPYRIGHT (C) Kepler Project",
_description = "WSAPI SAPI implementation",
_version = "WSAPI SAPI 1.0",
Ispersistent = False,
},
Request = {
servervariable = function (name) return Wsapi_env[name] end,
Getpostdata = function (n) return Wsapi_env.input:read (n) End
},
Response = {
ContentType = function (header)
Res:content_type (header)
End
errorlog = function (msg, errlevel)
Wsapi_env.error:write (msg)
End
Header = function (header, value)
If Res.headers[header] Then
If Type (res.headers[header]) = = "Table" Then
Table.insert (Res.headers[header], value)
Else
Res.headers[header] = {Res.headers[header], value}
End
Else
Res.headers[header] = value
End
End
redirect = function (URL)
Res.status = 302
res.headers["location"] = URL
End
Write = function (...)
Res:write ({...})
End
},
}
Local Cgilua = require "Cgilua"
Cgilua.main ()
Return Res:finish ()
End
Return _m
At this point, the invocation process for THTTPD to Cgilua has been clarified.
Admittedly, the CGI run mode, which processes requests for the initiating subprocess, starts a separate CGI execution for each request and exits after execution.
This can be a problem of efficiency, for static resources, such as pure HTML and CSS pictures, should not go CGI program.
Ways to resolve this problem:
1, the processing of CGI script is fixed in the thttpd process. (is openresty this mode?) )
2, use fastcgi instead. (Next stage study)
THTTPD and Cgilua installation and operation process Analysis