THTTPD and Cgilua installation and operation process Analysis

Source: Internet
Author: User
Tags lua sapi

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-&GT;HS-&GT;CWD) + strlen (hc->pathinfo) + 1;
CP2 = NEW (char, L);
if (cp2! = (char*) 0)
{
(void) my_snprintf (CP2, L, "%s%s", HC-&GT;HS-&GT;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 (&AMP;HC-&GT;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-&GT;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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.