📜  Perl-CGI编程

📅  最后修改于: 2020-10-16 05:42:16             🧑  作者: Mango


什么是CGI?

  • 通用网关接口(CGI)是一组标准,用于定义如何在Web服务器和自定义脚本之间交换信息。

  • CGI规范目前由NCSA维护,NCSA定义CGI如下-

  • 通用网关接口(CGI)是外部网关程序与信息服务器(例如HTTP服务器)接口的标准。

  • 当前版本是CGI / 1.1,CGI / 1.2正在开发中。

网页浏览

为了理解CGI的概念,让我们看看单击网页上的超级链接来浏览特定网页或URL时会发生什么。

  • 您的浏览器使用HTTP协议与Web服务器联系,并要求提供URL,即网页文件名。

  • Web服务器将检查URL,并将查找请求的文件名。如果Web服务器找到该文件,则它将文件发送回浏览器,而无需进一步执行,否则发送一条错误消息,表明您请求了错误的文件。

  • Web浏览器从Web服务器获取响应,并在未找到文件的情况下显示接收到的文件内容或错误消息。

但是,可以通过以下方式设置HTTP服务器,以便每当请求某个目录中的文件时,该文件都不会被发回。而是将其作为程序执行,并且无论该程序输出的结果如何,都将其发送回浏览器以显示。这可以通过使用Web服务器中可用的特殊功能来完成,它被称为Common Gateway Interface或CGI,而由服务器执行以产生最终结果的此类程序称为CGI脚本。这些CGI程序可以是PERL脚本,Shell脚本,C或C++程序等。

CGI架构图

CGI架构

Web服务器支持和配置

在继续进行CGI编程之前,请确保您的Web服务器支持CGI功能并将其配置为处理CGI程序。 Web服务器要执行的所有CGI程序都保存在预先配置的目录中。该目录称为CGI目录,按照约定,其命名为/ cgi-bin。按照约定,Perl CGI文件的扩展名为.cgi

第一个CGI程序

这是一个简单的链接,链接到一个名为hello.cgi的CGI脚本。该文件已保存在/ cgi-bin /目录中,并且具有以下内容。在运行CGI程序之前,请确保使用chmod 755 hello.cgi UNIX命令更改文件的模式。

#!/usr/bin/perl

print "Content-type:text/html\r\n\r\n";
print '';
print '';
print 'Hello Word - First CGI Program';
print '';
print '';
print '

Hello Word! This is my first CGI program

'; print ''; print ''; 1;

现在,如果您单击hello.cgi链接,那么请求将发送到Web服务器,该服务器在/ cgi-bin目录中搜索hello.cgi,执行该命令,并生成任何结果,Web服务器将该结果发送回Web浏览器,如下所示-

Hello Word! This is my first CGI program

这个hello.cgi脚本是一个简单的Perl脚本,它在STDOUT文件(即屏幕)上写入其输出。有一个重要的额外功能可用,即要打印的第一行Content-type:text / html \ r \ n \ r \ n 。该行被发送回浏览器,并指定要在浏览器屏幕上显示的内容类型。现在您必须具备CGI的基本概念,并且可以使用Perl编写许多复杂的CGI程序。该脚本还可以与任何其他工具系统进行交互,以交换信息,例如数据库,Web服务或任何其他复杂的界面。

了解HTTP标头

第一行Content-type:text / html \ r \ n \ r \ n是HTTP标头的一部分,发送到浏览器,以便浏览器可以理解来自服务器端的传入内容。所有HTTP标头将采用以下形式-

HTTP Field Name: Field Content

例如-

Content-type:text/html\r\n\r\n

其他几个重要的HTTP标头,在CGI编程中将经常使用。

Sr.No. Header & Description
1

Content-type: String

A MIME string defining the format of the content being returned. Example is Content-type:text/html

2

Expires: Date String

The date when the information becomes invalid. This should be used by the browser to decide when a page needs to be refreshed. A valid date string should be in the format 01 Jan 1998 12:00:00 GMT.

3

Location: URL String

The URL that should be returned instead of the URL requested. You can use this filed to redirect a request to any other location.

4

Last-modified: String

The date of last modification of the file.

5

Content-length: String

The length, in bytes, of the data being returned. The browser uses this value to report the estimated download time for a file.

6

Set-Cookie: String

Set the cookie passed through the string

CGI环境变量

所有CGI程序都可以访问以下环境变量。这些变量在编写任何CGI程序时都起着重要作用。

Sr.No. Variables Names & Description
1

CONTENT_TYPE

The data type of the content. Used when the client is sending attached content to the server. For example file upload, etc.

2

CONTENT_LENGTH

The length of the query information. It’s available only for POST requests

3

HTTP_COOKIE

Returns the set cookies in the form of key & value pair.

4

HTTP_USER_AGENT

The User-Agent request-header field contains information about the user agent originating the request. Its name of the web browser.

5

PATH_INFO

The path for the CGI script.

6

QUERY_STRING

The URL-encoded information that is sent with GET method request.

7

REMOTE_ADDR

The IP address of the remote host making the request. This can be useful for logging or for authentication purpose.

8

REMOTE_HOST

The fully qualified name of the host making the request. If this information is not available then REMOTE_ADDR can be used to get IR address.

9

REQUEST_METHOD

The method used to make the request. The most common methods are GET and POST.

10

SCRIPT_FILENAME

The full path to the CGI script.

11

SCRIPT_NAME

The name of the CGI script.

12

SERVER_NAME

The server’s hostname or IP Address.

13

SERVER_SOFTWARE

The name and version of the software the server is running.

这是一个小型CGI程序,用于列出您的Web服务器支持的所有CGI变量。单击此链接以查看结果获取环境

#!/usr/bin/perl

print "Content-type: text/html\n\n";
print "Environment\n";
foreach (sort keys %ENV) {
   print "$_: $ENV{$_}
\n"; } 1;

引发“文件下载”对话框?

有时,您希望提供一个选项,使用户单击链接,该链接将向用户弹出“文件下载”对话框,而不显示实际内容。这非常简单,可以通过HTTP标头实现。

此HTTP标头将与上一节中提到的标头不同。例如,如果您要使FileName文件可从给定链接下载,则其语法如下-

#!/usr/bin/perl

# HTTP Header
print "Content-Type:application/octet-stream; name = \"FileName\"\r\n";
print "Content-Disposition: attachment; filename = \"FileName\"\r\n\n";

# Actual File Content will go hear.
open( FILE, "

GET和POST方法

当您需要将一些信息从浏览器传递到Web服务器,并最终传递给处理您的请求的CGI程序时,您肯定遇到过许多情况。浏览器最经常使用两种方法将此信息传递到Web服务器。这些方法是GET方法和POST方法。让我们一一检查。

使用GET方法传递信息

GET方法发送附加到页面URL本身的编码用户信息。页面和编码信息由?分隔。字符如下-

http://www.test.com/cgi-bin/hello.cgi?key1=value1&key2=value2

GET方法是将信息从浏览器传递到Web服务器的默认方法,它生成一个长字符串,该字符串出现在浏览器的Location:框中。如果您有密码或其他敏感信息要传递到服务器,则永远不要使用GET方法。 GET方法具有大小限制:在请求字符串只能传递1024个字符。

此信息使用QUERY_STRING标头传递,并且可以通过QUERY_STRING环境变量在您的CGI程序中访问,您可以在CGI程序中解析和使用该环境变量。

您可以通过简单地将键和值对与任何URL串联来传递信息,也可以使用HTML

标记使用GET方法传递信息。

简单的URL示例:获取方法

这是一个简单的URL,它将使用GET方法将两个值传递给hello_get.cgi程序。

http://www.tutorialspoint.com/cgi-bin/hello_get.cgi?first_name=ZARA&last_name=ALI

下面是hello_get.cgi脚本,用于处理Web浏览器给出的输入。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "GET") {
   $buffer = $ENV{'QUERY_STRING'};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$first_name = $FORM{first_name};
$last_name  = $FORM{last_name};

print "Content-type:text/html\r\n\r\n";
print "";
print "";
print "Hello - Second CGI Program";
print "";
print "";
print "

Hello $first_name $last_name - Second CGI Program

"; print ""; print ""; 1;

简单的FORM示例:GET方法

这是一个简单的示例,该示例使用HTML FORM和Submit按钮传递两个值。我们将使用相同的CGI脚本hello_get.cgi来处理此输入。


First Name:   
Last Name:

这是上述表单编码的实际输出。现在,您可以输入名字和姓氏,然后单击提交按钮以查看结果。

名字:

姓:

使用POST方法传递信息

将信息传递到CGI程序的一种更可靠的方法是POST方法。这将以与GET方法完全相同的方式打包信息,但不是在之后将其作为文本字符串发送在URL中,它将作为单独的消息作为HTTP标头的一部分发送。 Web服务器以标准输入的形式将此消息提供给CGI脚本。

下面是修改后的hello_post.cgi脚本,用于处理Web浏览器给出的输入。该脚本将处理GET和POST方法。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST") {
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
} else {
   $buffer = $ENV{'QUERY_STRING'};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$first_name = $FORM{first_name};
$last_name  = $FORM{last_name};

print "Content-type:text/html\r\n\r\n";
print "";
print "";
print "Hello - Second CGI Program";
print "";
print "";
print "

Hello $first_name $last_name - Second CGI Program

"; print ""; print ""; 1;

让我们再次采用与上述相同的示例,该示例使用HTML FORM和Submit按钮传递两个值。我们将使用CGI脚本hello_post.cgi来处理此输入。

First Name:
Last Name:

这是上述表单编码的实际输出,您输入名和姓,然后单击提交按钮以查看结果。

名字:

姓:

将复选框数据传递到CGI程序

当需要选择多个选项时,将使用复选框。这是带有两个复选框的表单的示例HTML代码。

Maths Physics

此代码的结果是以下形式-

数学物理

下面是checkbox.cgi脚本,用于处理Web浏览器为单选按钮提供的输入。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST") {
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
} else {
   $buffer = $ENV{'QUERY_STRING'};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
if( $FORM{maths} ) {
   $maths_flag ="ON";
} else {
   $maths_flag ="OFF";
}
if( $FORM{physics} ) {
   $physics_flag ="ON";
} else {
   $physics_flag ="OFF";
}

print "Content-type:text/html\r\n\r\n";
print "";
print "";
print "Checkbox - Third CGI Program";
print "";
print "";
print "

CheckBox Maths is : $maths_flag

"; print "

CheckBox Physics is : $physics_flag

"; print ""; print ""; 1;

将单选按钮数据传递到CGI程序

当只需要选择一个选项时,使用单选按钮。这是带有两个单选按钮的表单的示例HTML代码-

Maths Physics

此代码的结果是以下形式-

数学物理

下面是radiobutton.cgi脚本,用于处理Web浏览器为单选按钮提供的输入。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST") {
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
} else {
   $buffer = $ENV{'QUERY_STRING'};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$subject = $FORM{subject};

print "Content-type:text/html\r\n\r\n";
print "";
print "";
print "Radio - Fourth CGI Program";
print "";
print "";
print "

Selected Subject is $subject

"; print ""; print ""; 1;

将文本区域数据传递到CGI程序

当必须将多行文本传递给CGI程序时,将使用textarea元素。这是带有TEXTAREA框的表单的示例HTML代码-

此代码的结果是以下形式-

下面是textarea.cgi脚本,用于处理Web浏览器给出的输入。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST") {
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
} else {
   $buffer = $ENV{'QUERY_STRING'};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$text_content = $FORM{textcontent};

print "Content-type:text/html\r\n\r\n";
print "";
print "";
print "Text Area - Fifth CGI Program";
print "";
print "";
print "

Entered Text Content is $text_content

"; print ""; print ""; 1;

将下拉框数据传递到CGI程序

当我们有许多可用选项,但只选择一个或两个时,将使用一个下拉框。这是带有一个下拉框的表单的示例HTML代码

此代码的结果是以下形式-

以下是dropdown.cgi脚本,用于处理Web浏览器给出的输入。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST") {
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
} else {
   $buffer = $ENV{'QUERY_STRING'};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$subject = $FORM{dropdown};

print "Content-type:text/html\r\n\r\n";
print "";
print "";
print "Dropdown Box - Sixth CGI Program";
print "";
print "";
print "

Selected Subject is $subject

"; print ""; print ""; 1;

在CGI中使用Cookie

HTTP协议是无状态协议。但是对于商业网站,需要在不同页面之间维护会话信息。例如,一个用户注册在跨越多个页面的交易之后结束。但是,如何在所有网页上维护用户的会话信息?

在许多情况下,使用Cookie是记住和跟踪偏好,购买,佣金和其他信息(以获得更好的访问者体验或站点统计信息所需)的最有效方法。

怎么运行的

您的服务器以cookie的形式向访问者的浏览器发送一些数据。浏览器可以接受该cookie。如果是这样,它将以纯文本记录的形式存储在访问者的硬盘上。现在,当访问者到达您网站上的另一个页面时,就可以检索该cookie。一旦检索到,您的服务器就知道/记住存储了什么。

Cookies是5个可变长度字段的纯文本数据记录-

  • 过期-Cookie过期的日期。如果为空,则cookie将在访问者退出浏览器时过期。

  • -您站点的域名。

  • 路径-设置cookie的目录或网页的路径。如果要从任何目录或页面检索cookie,则该字段可以为空白。

  • 安全-如果此字段包含“安全”一词,则只能使用安全服务器检索cookie。如果此字段为空白,则不存在此类限制。

  • 名称=值-Cookies以键和值对的形式设置和重新查看。

设置Cookie

将cookie发送到浏览器非常容易。这些cookie将与HTTP标头一起发送。假设您要将UserID和Password设置为cookie。所以它将完成如下-

#!/usr/bin/perl

print "Set-Cookie:UserID = XYZ;\n";
print "Set-Cookie:Password = XYZ123;\n";
print "Set-Cookie:Expires = Tuesday, 31-Dec-2007 23:12:40 GMT";\n";
print "Set-Cookie:Domain = www.tutorialspoint.com;\n";
print "Set-Cookie:Path = /perl;\n";
print "Content-type:text/html\r\n\r\n";
...........Rest of the HTML Content goes here....

在这里,我们使用Set-Cookie HTTP标头设置cookie。可以选择设置cookie属性,例如Expires,Domain和Path。重要的是要注意,在发送魔术行“ Content-type:text / html \ r \ n \ r \ n”之前已设置cookie。

检索Cookie

检索所有设置的cookie非常容易。 Cookies存储在CGI环境变量HTTP_COOKIE中,它们具有以下形式。

key1 = value1;key2 = value2;key3 = value3....

这是有关如何获取Cookie的示例。

#!/usr/bin/perl
$rcvd_cookies = $ENV{'HTTP_COOKIE'};
@cookies = split /;/, $rcvd_cookies;
foreach $cookie ( @cookies ) {
   ($key, $val) = split(/=/, $cookie); # splits on the first =.
   $key =~ s/^\s+//;
   $val =~ s/^\s+//;
   $key =~ s/\s+$//;
   $val =~ s/\s+$//;
   if( $key eq "UserID" ) {
      $user_id = $val;
   } elsif($key eq "Password") {
      $password = $val;
   }
}
print "User ID  = $user_id\n";
print "Password = $password\n";

如果在调用检索cookie脚本之前已设置了以上cookie,这将产生以下结果。

User ID = XYZ
Password = XYZ123

CGI模块和库

您会在Internet上找到许多内置模块,这些模块为您提供了直接功能,可以在CGI程序中使用。以下是重要的一次。