初识CGI

CGI

Web 服务器只能生成静态内容,而用户请求动态内容时,Web服务器只能借助一些应用程序来实现。CGI时一套标准,它规定了Web服务器和应用程序之间的交互方式。

静态内容与动态内容

要想理解什么是CGI,首先需要什么是静态内容和动态内容。

静态内容:web 服务器读取一个磁盘文件,并将其内容返回给客户端。磁盘文件的称为静态内容,而返回文件给客户端的过程称为服务静态内容

动态内容:web服务器运行一个可执行程序,并将它的输出结果返回给客户端。运行时可执行文件产生的输出称为动态内容。而运行程序并返回它的输出到客户端的过程称为服务动态内容

服务动态内容

​ 在web服务器服务动态内容时,一般需要创建一个子进程来运行可执行程序。在程序运行时时回读取用户提供的一些参数,比如一个加法程序需要读入加数和被加数,那么用户如何将程序参数传递给服务器?而服务器如何将这些参数传递给它所创建的子进程?子进程将它的输出又发送到哪里?CGI的出现则解决了这些问题。CGI是一套标准,规定了web服务器与可执行程序之间的交互方式,关于其具体说明可以参考RFC3875文档。

​ 在对客户端请求的处理过程中,web服务器扮演着应用网关的角色。它接受来自客户端的请求,将客户端请求转为一个CGI请求,然后选择一个可执行文件(CGI脚本)去处理CGI请求。CGI脚本的执行结果称为CGI响应,web服务器将CGI响应转为客户端响应,将其发送给客户端。在实际应用中,web服务器负责处理与客户端请求有关的传输和网络问题,它会根据CGI标准将请求中一些参数写到环境变量中,然后CGI脚本从环境变量(environment variables)和标准输入(standard input)中读取数据、处理数据、向标准输出(standard output)输出数据。

服务器将参数传递给子进程

在服务器接受到一个如下的请求后:

GET /cgi-bin/add?100&200 HTTP/1.1

它调用fork来创建一个子进程,并调用execve在子进程的上下文中执行/cgi-bin/add程序。像add这样的程序被称作CGI程序,因为它遵循CGI标准。在调用execve之前,子进程将CGI环境变量QUERY_STRING设置为“100&200”,add程序在运行时可以用getenv函数来读取环境变量的值。

服务器如何将其他信息传递给子进程

CGI定义了大量的其他环境变量,一个CGI程序在它运行时可以设置这些环境变量。下表中给出了其中的一部分:

环境变量 描述
QUERY_STRING 程序参数
SERVER_PORT 父进程监听端口
REQUESET_METHOD GET或POST
REMOTE_HOST 客户端域名
REMOTE_ADDR 客户端中点分十进制IP地址
CONTENT_TYPE 对于POST而言,请求体的MIME类型
CONTENT_LENGTH 对于POST而言,请求体字节大小

服务器可以将一些信息写到对应的环境变量中,而客户端则从环境变量中读取这些信息。

子进程将它的输出发送到哪

一个CGI程序将它的动态内容发送到标准输出。在子进程加载并运行CGI程序之前,它使用Linux dup2函数将标准输出重定向到和客户端相关联的已连接描述符。因此,任何CGI程序写到标准输出的东西都会直接到客户端。

CGI实战

通过具体的案例来理解什么时CGI,以及CGI在实际中时如何被应用的。环境为Ubuntu16,Apache2。

启动CGI模块

  • 如果apache工作在prefork模式,加载CGI模块 sudo a2enmod cgi
  • 如果apache工作在worker模式,加载CGID模块sudo a2enmod cgid
  • 可以通过** apache2ctl -t -D DUMP_MODULES **指令来查看加载prefork模块还是worker模块,从而判断其工作模式

启用CGI配置文件

CGI配置文件位于/etc/apache2/conf-avaliable目录下,将其软连接到/etc/apache2/conf-enabled目录下,或者直接使用命令sudo a2enconf serve-cgi-bin, 配置文件内容修改如下,其中/usr/lib/cgi-bin用于存放CGI脚本:

<IfModule mod_alias.c>                                                                                       <IfModule mod_cgi.c>
                Define ENABLE_USR_LIB_CGI_BIN
        </IfModule>
        <IfModule mod_cgid.c>
                Define ENABLE_USR_LIB_CGI_BIN
        </IfModule>
        <IfDefine ENABLE_USR_LIB_CGI_BIN>
                ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
                <Directory "/usr/lib/cgi-bin">
                        AllowOverride None
                        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                        AddHandler cgi-script .cgi
                        Require all granted
                </Directory>
        </IfDefine>
</IfModule>

编写CGI程序

CGI程序可以以任何语言编写,我们这里使用C语言编写。代码如下:

#include<stdio.h>                                                                                                
int main() {
  	printf("Content-Type: text/html\n\n");   #这行代码必须加
    printf("hello world!");
    return 0;
}

将代码保存到test.c文件中,使用gcc对其进行编译生成可执行文件test.cgi,将test.cgi放置在/usr/lib/cgi-bin目录中,这里需要为test.cgi赋予可执行权限。

访问CGI程序

重启apache2服务器:systemctl restart apache2

在浏览器输入:http://地址/cgi-bin/test.cgi

补充

Apache不仅可以配置CGI方式,也可以配置模块方式,而其默认方式模块方式。PHP就是以模块方式在Apache上进行运行的。,关于Apache的其他方式可以参考链接。

参考

posted @ 2018-05-12 16:40  被罚站的树  阅读(1282)  评论(0编辑  收藏  举报