CGI动态页面
mod_alias
mod_cgi
CGI(公共网关接口)定义了web服务器与外部内容生成程序之间交互的方法,通常是指CGI程序或者CGI脚本,它是在网站上实现动态页面的最简单和常用的方法。本文将对如何在Apache web服务器上建立CGI以及如何编写CGI程序进行介绍。
配置Apache以允许CGI
要让CGI程序能正常运作,必须配置Apache以允许CGI的执行,其方法有多种。
ScriptAlias
ScriptAlias
指令使Apache允许执行一个特定目录中的CGI程序。当客户端请求此特定目录中的资源时,Apache假定其中所有的文件都是CGI程序并试图运行它。
ScriptAlias
指令形如:
ScriptAlias /cgi-bin/ /usr/local/apache2/cgi-bin/
如果Apache被安装到默认位置,默认的配置文件httpd.conf
中就会有上述配置。ScriptAlias
与Alias
指令非常相似,都是定义了映射到一个特定目录的URL前缀,两者一般都用于指定位于DocumentRoot
以外的目录,其不同之处是ScriptAlias
又多了一层含义,即URL前缀后面的任何文件都被视为CGI程序。所以,上述例子会指示Apache:任何以/cgi-bin/
开头的资源都将映射到/usr/local/apache2/cgi-bin/
目录中,且视之为CGI程序。
例如,如果有URL为http://www.example.com/cgi-bin/test.pl
的请求,Apache会试图执行/usr/local/apache2/cgi-bin/test.pl
文件并返回其输出。当然,这个文件必须存在而且可执行,并以特定的方法产生输出,否则Apache返回一个出错消息。
ScriptAlias目录以外的CGI
由于安全原因,CGI程序通常被限制在ScriptAlias
指定的目录中,这样,管理员就可以严格控制谁可以使用CGI程序。但是,如果采取了恰当的安全措施,则没有理由不允许其他目录中的CGI程序运行。比如,你可能希望用户在UserDir
指定的宿主目录中存放页面,而他们有自己的CGI程序,但无权访问cgi-bin
目录,这样,就产生了运行其他目录中CGI程序的需求。
允许CGI在任意目录执行需要两个步骤:第一步,必须用AddHandler
或SetHandler
指令激活cgi-script
处理器。第二步,必须在Options
指令中启用ExecCGI
选项。
用Options显式地允许CGI的执行
可以在主配置文件中,使用Options
指令显式地允许特定目录中CGI的执行:
<Directory /usr/local/apache2/htdocs/somedir>
Options +ExecCGI
</Directory>
上述指令使Apache允许CGI文件的执行。另外,还必须告诉服务器哪些文件是CGI文件。下面的AddHandler
指令告诉服务器所有带有cgi
或pl
后缀的文件是CGI程序:
AddHandler cgi-script .cgi .pl
.htaccess
指南示范了怎样在没有权限修改httpd.conf
文件的情况下激活CGI程序。
用户目录
为了允许用户目录中所有以".cgi
"结尾的文件作为CGI程序执行,你可以使用以下配置:
<Directory /home/*/public_html>
Options +ExecCGI
AddHandler cgi-script .cgi
</Directory>
如果你想在用户目录中指定一个cgi-bin
子目录,其中所有的文件都被当作CGI程序,你可以这样配置:
<Directory /home/*/public_html/cgi-bin>
Options ExecCGI
SetHandler cgi-script
</Directory>
MIME类型的头,对客户端指明所接收内容的类型,大多数情况下,像这样:
Content-type: text/html
Content-type: text/html
其次,输出要求是HTML形式的,或者是浏览器可以显示的其他某种形式。多数情况下,输出是HTML形式的,但偶然也会输出一个gif图片或者其他非HTML的内容。
除了这两点,编写CGI程序和编写其他程序大致相同。
第一个CGI程序
这个CGI程序的例子在浏览器中打印一行文字。把下列存为first.pl
文件,并放在你的cgi-bin
目录中。
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "Hello, World.";
即使不熟悉Perl语言,你也应该能看出它干了什么。第一行,告诉Apache这个文件可以用/usr/bin/perl
(或者任何你正在使用的shell)解释并执行。第二行,打印上述要求的内容类型说明,并带有两个换行,在头后面留出空行,以示HTTP头的结束。第三行,打印文字"Hello, World."。程序到此结束。
打开你喜欢的浏览器并输入地址:
http://www.example.com/cgi-bin/first.pl
或者是你存放程序的其他位置,就可以在浏览器窗口中看到一行:Hello, World.
。虽然并不怎么激动人心,但是一旦这个程序能正常运行,那么就可能运行其他任何程序。
配置Apache看看遗漏了什么。
一个以"Forbidden"开头的消息
这说明有权限问题。参考Apache错误日志和下面的文件权限。
一个"Internal Server Error"消息
查阅Apache错误日志,可以找到CGI程序产生的出错消息"Premature end of script headers"。对此,需要检查下列各项,以找出不能产生正确HTTP头的原因。
环境变量,你要确保所需要的变量已经正确的由Apache进行了传递。
路径信息找到解释器)
路径信息找到解释器)
你最先看到的输出内容应当是一组HTTP头,包括Content-Type
和结尾的空行。如果你看到了别的什么东西,那么当你在服务器上试运行时,Apache会返回 Premature end of script headers
错误。参见上面的编写CGI程序以获得更多信息。
suexec允许CGI程序根据其所在虚拟主机或用户宿主目录的不同而以不同的用户权限运行。suexec有极其严格的权限校验,任何校验失败都会使CGI程序遭遇 Premature end of script headers
错误。
为了检查你是否使用了suexec ,运行 apachectl -V
并检查SUEXEC_BIN
的位置。如果Apache在启动时发现suexec
二进制文件正存在于此,那么suexec将会被激活。
除非你很精通suexec,否则请不要使用它。要禁用它,只要删除(或重命名)SUEXEC_BIN
所指定位置的suexec
二进制文件并重启服务器就可以了。如果你又想启用它,请首先阅读suexec文档以详细了解其运行机制,然后运行 suexec -V
命令找到suexec日志文件,并使用该日志文件找到你违反了哪条判断规则。
http://hoohoo.ncsa.uiuc.edu/cgi/env.html
这个简单的CGI程序列出了所有的环境变量,Apache发行版的cgi-bin
目录中还有一个类似的程序。注意,有些变量是必须的,有些则是可选的,所以你可能会看见一些官方列表中没有的变量。另外,Apache有多种方法可以在默认提供的变量之外增加你的专用环境变量。
#!/usr/bin/perl
print "Content-type: text/html\n\n";
foreach $key (keys %ENV) {
print "$key --> $ENV{$key}<br>";
}
STDIN 和 STDOUT
服务器和客户端之间的其他通讯都通过标准输入设备(STDIN
)和标准输出设备(STDOUT
)完成。通常,STDIN
是指键盘或者一个程序所作用的一个文件,STDOUT
指控制台或显示器。
当你POST
一个网络表格到一个CGI程序时,表格中的数据被捆扎为一个特殊形式通过STDIN
传送给CGI程序,这样,这个程序就可以处理这些数据,仿佛这些数据是来自键盘或者一个文件。
这种"特殊形式"很简单,一个字段名称及其值,中间用等号(=)连接,多个这样的字段对用与符号(&)连接。非常规字符,如空格、"&"号和"="号,被转换为其等值的十六进制以免出问题。整个字符串形如:
name=Rich%20Bowen&city=Lexington&state=KY&sidekick=Squirrel%20Monkey
有时,你会发现URL后面也会带有这样的字符串。这种形式会使服务器以这个字符串的内容设置环境变量QUERY_STRING
,称为GET
请求。你的HTML表格在FORM
标签中设置METHOD
属性,以指定传送数据的动作使用GET
或POST
。
你的程序必须把这个字符串分解以获得有用信息。所幸,有库和模块可以帮助你处理这些数据,还有为你的CGI程序达成其他目的的处理器。
CPAN ,最常用的模块是CGI.pm
。也可以考虑用CGI::Lite
,它实现了一个在多数程序中所有必须的最小功能集。
如果用C语言编写CGI程序,则有很多选择,其中之一是CGIC
库,来自http://www.boutell.com/cgic/
comp.infosystems.www.authoring.cgi和别人讨论CGI相关问题。HTML Writers Guild 的邮件列表是一个优秀的问题解答资源。更多资源在http://www.hwg.org/lists/hwg-servers/
另外,还可以阅读CGI规范,其中有CGI程序操作的所有细节,原始版本见NCSA ,另有一个更新草案见Common Gateway Interface RFC project
当你向一个邮件列表或者新闻组提交CGI相关问题时,你应该确保提供了足够的信息以更容易地发现并解决问题,诸如:发生了什么事、你希望得到什么结果、结果与你所期望的有什么出入、你运行的服务器、CGI程序是用什么语言编写的、如果可能就提供那个讨厌的代码。
注意,不要把CGI相关问题提交到Apache bug数据库,除非你坚信发现的是Apache源代码中的问题。