CGI Web Programming/zh CN
│
English (en) │
español (es) │
français (fr) │
Bahasa Indonesia (id) │
русский (ru) │
中文(中国大陆) (zh_CN) │
本文涉及简单的 CGI 程序。请注意,选用一种 Web 框架开发效率可能会更高。
关于 CGI
CGI(公共网关接口)的工作原理很简单:
假设有两台计算机:
- 服务器 - 存储了文件(网页、图象和 CGI),通过 Web 服务程序提供服务。
- 客户机 - 通常具备浏览器,请求访问服务器上的文件。
只有主机上的 Web 服务程序支持 CGI 功能,您才能使用 CGI。把所有文件放入主机后,CGI 程序通常可以如下启动: http://www.yourserver.com[.xx]/yourlogin/cgi-bin/cginame.exe
注意:
- CGI 程序文件扩展名不一定要是 .exe。
- CGI 显然应该根据服务器的平台进行编译(Linux、Windows……)。
Free Pascal CGI 程序及测试方式
和其他程序一样,用 Free Pascal 编写的 CGI 程序就是普通的可执行程序。与 Perl 或 Python 编写的 CGI 程序不同,用 Free Pascal 编写的 CGI 程序不是解释执行的,而是独立运行的可执行程序。
若要测试 CGI 程序,电脑中必须装有支持 CGI 功能的 HTTP 服务程序。 推荐一款优秀的 HTTP服务器:Apache,Windows 和 Linux 均可支持。
十分简单的示例
以下是一个迷你 CGI 程序的示例,仅供演示。
- 设置 Cookie
- 输出 Content-Type(即声明可输出合法的 HTTP 文本)
- 读取 Cookie
- 以 GET 方式读取表单数据
- 以 POST 方式读取表单数据
program mini;
uses dos;
var
a:string;
c:char;
begin
//set a cookie (must come before content-type line below)
//don't forget to change the expires date
writeln('Set-cookie:widget=value; path=/; expires= Mon, 21-Mar-2005 18:37:00 GMT');
//output legal http page
writeln('Content-Type:text/html',#10#13);
//demonstrate get cookies
a:= GetEnv('HTTP_COOKIE');
writeln('cookies:',a);
//demonstrate GET result
a:='';
a:= GetEnv('QUERY_STRING');
writeln('GET: ',a);
//demonstrate POST result
a:='';
while not eof(input) do
begin
read(c);
a:= a+c;
end;
writeln('POST: ',a);
end.
简单的点击计数程序
hitcounter程序可为网站提供简单的点击计数功能。可以考虑在配置文件中加入阻止列表,以便不把机器人程序和自己的计算机纳入统计。当然还可以有更多改进,比如设置 Cookie 让每个会话只能获得一次点击计数,但这已足以介绍 CGI 编程了。
代码在此:[1]
Debugging CGI
因为 CGI 程序不会往屏幕上显式信息,而且是由其他进程(Web 服务程序)启动的,调试起来要比桌面应用困难得多。
有一种解决方案是让 CGI 应用程序启动一个调试器: 程序引用单元代码时,作为初始化过程之一,将新开一个进程,该进程会打开终端(windows中的cmd、linux中的xterm)并启动附着于调用过程的 gdb 调试器。
这里主程序会暂时“Sleep”一会儿,以确保 gdb 能完成初始化。
这种方案已在以下平台通过测试:
- 带有 Apache 2.2 的 Windows XP 32位系统,运行为普通程序或系统服务(更高版本的 Windows 不适用,参见 http://forum.lazarus.freepascal.org/index.php/topic,21931.msg128849.html#msg128849)
- 带有 Apache 2.2 的 ubuntu 10.04 x64 系统
- 带有 Apache 2 的 Debian unstable x64 系统(2013年2月)
更多说明详见单元代码。
unit SelfDebug;
{
Instructions:
-Include unit anywhere in the program.
-Change DEBUGGER constant to match your debugger (gdb, ddd,gdbtui...)
-For Windows, if the program to debug is running as a service (e.g. CGI application
from Apache running as a service), make sure the service is configured with
"Interact with desktop" checked. Failing to do so, the debugger will be started
without a console, break the program and hang waiting for input. Killing the debugger
is your only option.
-For Linux, if the program to debug is running as a different user (e.g. CGI application),
run "xhost +" in a terminal to enable all users to connect to xserver.
If needed, change DISPLAY to match your DISPLAY environment variable
}
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,Process;
implementation
const
{$ifdef windows}
DEBUGGER='C:\lazarus\mingw\bin\7.3\gdb.exe';
{$endif}
{$ifdef linux}
DEBUGGER='gdb';
DISPLAY=':0.0';
{$endif}
MSWAIT=2000;
var
AProcess: TProcess;
initialization
AProcess := TProcess.Create(nil);
{$ifdef windows}
AProcess.CommandLine := format('cmd /C START "Debugging %s" /WAIT "%s" "%s" %d"',[paramstr(0),debugger,paramstr(0),GetProcessID]);
{$endif}
{$ifdef linux}
AProcess.CommandLine := format('xterm -display %s -T "Debugging %s" -e "%s" "%s" %d',[DISPLAY,paramstr(0),DEBUGGER,paramstr(0),GetProcessID]);
{$endif}
AProcess.Execute;
sleep(MSWAIT);
finalization
AProcess.Free;
end.
源代码:http://www.hu.freepascal.org/lists/fpc-pascal/2011-October/030752.html
有关调试的其他解决方案,是将调试信息写入文件或事件日志 log/syslog。
Existing CGI Frameworks
现成的 CGI 单元代码和框架已有很多了,而且能设置 Cookie、会话、读取 POST 和 GET 信息,因此直接使用 CGI 显得微末了。