CGI Web Programming/zh CN: what changed
Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.
| Old | New | Line | |
|---|---|---|---|
| 1 | - | ||
| 1 | + | 本文涉及简单的 CGI 程序。请注意,选用一种 Web 框架开发效率可能会更高。 | |
| 2 | 2 | ||
| 3 | - | ||
| 3 | + | ## 关于 CGI | |
| 4 | 4 | ||
| 5 | - | ||
| 5 | + | [**CGI** (公共网关接口)](<http://en.wikipedia.org/wiki/Common_Gateway_Interface>)的工作原理很简单: | |
| 6 | 6 | ||
| 7 | - | ||
| 7 | + | 假设有两台计算机: | |
| 8 | 8 | ||
| 9 | - | ||
| 9 | + | * 服务器 - 存储了文件(网页、图象和 CGI),通过 Web 服务程序提供服务。 | |
| 10 | + | * 客户机 - 通常具备浏览器,请求访问服务器上的文件。 | |
| 10 | 11 | ||
| 11 | - | ||
| 12 | + | 只有主机上的 Web 服务程序支持 CGI 功能,您才能使用 CGI。把所有文件放入主机后,CGI 程序通常可以如下启动: **http://www.yourserver.com[.xx]/yourlogin/cgi-bin/cginame.exe** | |
| 12 | 13 | ||
| 13 | - | ||
| 14 | - | ||
| 14 | + | **注意:** | |
| 15 | 15 | ||
| 16 | - | ||
| 16 | + | * CGI 程序文件扩展名不一定要是 **.exe** 。 | |
| 17 | + | * CGI 显然应该根据服务器的平台进行编译(Linux、Windows……)。 | |
| 17 | 18 | ||
| 18 | - | ||
| 19 | + | ## Free Pascal CGI 程序及测试方式 | |
| 19 | 20 | ||
| 20 | - | ||
| 21 | + | 和其他程序一样,用 Free Pascal 编写的 CGI 程序就是普通的可执行程序。与 Perl 或 Python 编写的 CGI 程序不同,用 Free Pascal 编写的 CGI 程序不是解释执行的,而是独立运行的可执行程序。 | |
| 21 | 22 | ||
| 22 | - | ||
| 23 | - | ||
| 23 | + | 若要测试 CGI 程序,电脑中必须装有支持 CGI 功能的 **HTTP 服务** 程序。 推荐一款优秀的 [HTTP服务器](<http://en.wikipedia.org/wiki/HTTP_Server>):[Apache](<http://en.wikipedia.org/wiki/Apache_HTTP_Server>),Windows 和 Linux 均可支持。 | |
| 24 | 24 | ||
| 25 | - | ||
| 25 | + | ## 十分简单的示例 | |
| 26 | 26 | ||
| 27 | - | ||
| 27 | + | 以下是一个迷你 CGI 程序的示例,仅供演示。 | |
| 28 | 28 | ||
| 29 | - | ||
| 29 | + | 1. 设置 Cookie | |
| 30 | + | 2. 输出 Content-Type(即声明可输出合法的 HTTP 文本) | |
| 31 | + | 3. 读取 Cookie | |
| 32 | + | 4. 以 GET 方式读取表单数据 | |
| 33 | + | 5. 以 POST 方式读取表单数据 | |
| 30 | 34 | ||
| 31 | - | ||
| 35 | + | ``` | |
| 36 | + | program mini; | |
| 37 | + | ||
| 38 | + | uses dos; | |
| 39 | + | ||
| 40 | + | var | |
| 41 | + | a:string; | |
| 42 | + | c:char; | |
| 43 | + | begin | |
| 44 | + | //set a cookie (must come before content-type line below) | |
| 45 | + | //don't forget to change the expires date | |
| 46 | + | writeln('Set-cookie:widget=value; path=/; expires= Mon, 21-Mar-2005 18:37:00 GMT'); | |
| 47 | + | ||
| 48 | + | //output legal http page | |
| 49 | + | writeln('Content-Type:text/html',#10#13); | |
| 50 | + | ||
| 51 | + | //demonstrate get cookies | |
| 52 | + | a:= GetEnv('HTTP_COOKIE'); | |
| 53 | + | writeln('cookies:',a); | |
| 54 | + | ||
| 55 | + | //demonstrate GET result | |
| 56 | + | a:=''; | |
| 57 | + | a:= GetEnv('QUERY_STRING'); | |
| 58 | + | writeln('GET: ',a); | |
| 59 | + | ||
| 60 | + | //demonstrate POST result | |
| 61 | + | a:=''; | |
| 62 | + | while not eof(input) do | |
| 63 | + | begin | |
| 64 | + | read(c); | |
| 65 | + | a:= a+c; | |
| 66 | + | end; | |
| 67 | + | writeln('POST: ',a); | |
| 68 | + | end. | |
| 69 | + | ``` | |
| 32 | 70 | ||
| 33 | - | ||
| 71 | + | ## 简单的点击计数程序 | |
| 34 | 72 | ||
| 35 | - | ||
| 73 | + | **hitcounter** 程序可为网站提供简单的点击计数功能。可以考虑在配置文件中加入阻止列表,以便不把机器人程序和自己的计算机纳入统计。当然还可以有更多改进,比如设置 Cookie 让每个会话只能获得一次点击计数,但这已足以介绍 CGI 编程了。 | |
| 36 | 74 | ||
| 37 | - | ||
| 75 | + | 代码在此:[[1]](<http://sourceforge.net/p/modelbuilder/code/HEAD/tree/html/cgi/>) | |
| 38 | 76 | ||
| 39 | - | ||
| 40 | - | ||
| 41 | - | ||
| 42 | - | ||
| 43 | - | ||
| 77 | + | ## Debugging CGI | |
| 44 | 78 | ||
| 45 | - | ||
| 46 | - | ||
| 79 | + | 因为 CGI 程序不会往屏幕上显式信息,而且是由其他进程(Web 服务程序)启动的,调试起来要比桌面应用困难得多。 | |
| 47 | 80 | ||
| 48 | - | ||
| 81 | + | 有一种解决方案是让 CGI 应用程序启动一个调试器: 程序引用单元代码时,作为初始化过程之一,将新开一个进程,该进程会打开终端(windows中的cmd、linux中的xterm)并启动附着于调用过程的 gdb 调试器。 | |
| 49 | 82 | ||
| 50 | - | ||
| 51 | - | ||
| 52 | - | ||
| 53 | - | ||
| 54 | - | ||
| 55 | - | ||
| 56 | - | ||
| 83 | + | 这里主程序会暂时“Sleep”一会儿,以确保 gdb 能完成初始化。 | |
| 57 | 84 | ||
| 58 | - | ||
| 59 | - | ||
| 85 | + | 这种方案已在以下平台通过测试: | |
| 60 | 86 | ||
| 61 | - | ||
| 62 | - | ||
| 63 | - | ||
| 64 | - | ||
| 65 | - | ||
| 66 | - | ||
| 67 | - | ||
| 68 | - | ||
| 87 | + | * 带有 Apache 2.2 的 Windows XP 32位系统,运行为普通程序或系统服务(更高版本的 Windows 不适用,参见 <http://forum.lazarus.freepascal.org/index.php/topic,21931.msg128849.html#msg128849)> | |
| 88 | + | * 带有 Apache 2.2 的 ubuntu 10.04 x64 系统 | |
| 89 | + | * 带有 Apache 2 的 Debian unstable x64 系统(2013年2月) | |
| 90 | + | ||
| 91 | + | 更多说明详见单元代码。 | |
| 92 | + | ``` | |
| 93 | + | unit SelfDebug; | |
| 69 | 94 | ||
| 70 | - | ||
| 71 | - | ||
| 72 | - | ||
| 73 | - | ||
| 74 | - | ||
| 75 | - | ||
| 76 | - | ||
| 77 | - | ||
| 78 | - | ||
| 95 | + | { | |
| 96 | + | Instructions: | |
| 97 | + | -Include unit anywhere in the program. | |
| 98 | + | -Change DEBUGGER constant to match your debugger (gdb, ddd,gdbtui...) | |
| 99 | + | -For Windows, if the program to debug is running as a service (e.g. CGI application | |
| 100 | + | from Apache running as a service), make sure the service is configured with | |
| 101 | + | "Interact with desktop" checked. Failing to do so, the debugger will be started | |
| 102 | + | without a console, break the program and hang waiting for input. Killing the debugger | |
| 103 | + | is your only option. | |
| 104 | + | -For Linux, if the program to debug is running as a different user (e.g. CGI application), | |
| 105 | + | run "xhost +" in a terminal to enable all users to connect to xserver. | |
| 106 | + | If needed, change DISPLAY to match your DISPLAY environment variable | |
| 107 | + | } | |
| 108 | + | ||
| 109 | + | {$mode objfpc}{$H+} | |
| 110 | + | ||
| 111 | + | interface | |
| 112 | + | ||
| 113 | + | uses | |
| 114 | + | Classes, SysUtils,Process; | |
| 115 | + | ||
| 116 | + | implementation | |
| 117 | + | ||
| 118 | + | const | |
| 119 | + | {$ifdef windows} | |
| 120 | + | DEBUGGER='C:\lazarus\mingw\bin\7.3\gdb.exe'; | |
| 121 | + | {$endif} | |
| 122 | + | {$ifdef linux} | |
| 123 | + | DEBUGGER='gdb'; | |
| 124 | + | DISPLAY=':0.0'; | |
| 125 | + | {$endif} | |
| 126 | + | MSWAIT=2000; | |
| 127 | + | ||
| 128 | + | var | |
| 129 | + | AProcess: TProcess; | |
| 130 | + | ||
| 131 | + | initialization | |
| 132 | + | AProcess := TProcess.Create(nil); | |
| 133 | + | {$ifdef windows} | |
| 134 | + | AProcess.CommandLine := format('cmd /C START "Debugging %s" /WAIT "%s" "%s" %d"',[paramstr(0),debugger,paramstr(0),GetProcessID]); | |
| 135 | + | {$endif} | |
| 136 | + | {$ifdef linux} | |
| 137 | + | AProcess.CommandLine := format('xterm -display %s -T "Debugging %s" -e "%s" "%s" %d',[DISPLAY,paramstr(0),DEBUGGER,paramstr(0),GetProcessID]); | |
| 138 | + | {$endif} | |
| 139 | + | AProcess.Execute; | |
| 140 | + | sleep(MSWAIT); | |
| 141 | + | finalization | |
| 142 | + | AProcess.Free; | |
| 143 | + | end. | |
| 79 | 144 | ``` | |
| 80 | 145 | ||
| 81 | - | ||
| 82 | - | ||
| 83 | - | ||
| 146 | + | 源代码:<http://www.hu.freepascal.org/lists/fpc-pascal/2011-October/030752.html> | |
| 84 | 147 | ||
| 85 | - | ||
| 148 | + | 有关调试的其他解决方案,是将调试信息写入文件或事件日志 log/syslog。 | |
| 86 | 149 | ||
| 87 | 150 | ## Existing CGI Frameworks | |
| 88 | 151 | ||
| 89 | - | ||
| 90 | - | ||
| 91 | - | ||
| 152 | + | 现成的 CGI 单元代码和框架已有很多了,而且能设置 Cookie、会话、读取 POST 和 GET 信息,因此直接使用 CGI 显得微末了。 | |
| 92 | 153 | ||
| 93 | - | ||
| 154 | + | * 请参阅 [[Brook for Free Pascal]],完美的 Free Pascal Web 应用程序框架。 | |
| 155 | + | * 请参阅 [FastPlaz](<http://www.fastplaz.com/>),MVC 风格的 Free Pascal Web 应用程序框架。 | |
| 156 | + | * 请参阅 [[fcl-web]],FPC 和 Lazarus (weblaz)框架 | |
| 157 | + | * 请参阅 [Powtils](<http://z505.com/powtils/idx.shtml>) | |
| 158 | + | * [ExtPascal](<http://extpascal.googlecode.com>),Ext JS 封装。 | |
| 159 | + | * 请参阅 [Fano 框架](<https://fanoframework.github.io/>),现代 Pascal 编程语言的 Web 应用程序框架,用Free Pascal 编写。 | |
| 94 | 160 | ||
| 95 | 161 | --- | |
| 96 | - | ||
| 162 | + | *From the Free Pascal wiki, page "CGI Web Programming/zh CN", as the Internet Archive kept it on 2025-02-11, last changed on 2024-09-22. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
