感谢您的光临! Learnfk在线教程网正在翻译编辑中,请您稍等(v^_^)v Learnfk在线教程网
英文链接源链接 [413]
contenteditable="true"

Perl - CGI Programming 介绍

什么是CGI?

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

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

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

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

网页浏览

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

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

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

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

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

CGI架构图

CGI Architecture

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 '<html>';
print '<head>';
print '<title>Hello Word - 第一个CGI程序</title>';
print '</head>';
print '<body>';
print '<h2>你好,世界!这是我的第一个CGI程序</h2>';
print '</body>';
print '</html>';

1;

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

你好,世界!这是我的第一个CGI程序

这个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

定义返回的内容格式的MIME字符串。Example是Content-type:text/html

2

Expires:Date String

信息失效的日期。浏览器应使用它来决定何时需要刷新页面。有效的日期字符串的格式应为格林尼治标准时间1998年1月1日12:00:00。

3

Location:URL String

应该返回的URL而不是请求的URL。您可以使用此字段将请求重定向到任何其他位置。

4

Last-modified:String

文件的最后修改日期。

5

Content-length:String

返回的数据的长度(以字节为单位)。浏览器使用此值报告文件的估计下载时间。

6

Set-Cookie:String

设置通过 string 传递的cookie

CGI环境变量

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

Sr.No.Variables Names & Description
1

CONTENT_TYPE

内容的数据类型。客户端将附件内容发送到服务器时使用。如文件上传等。

2

CONTENT_LENGTH

查询信息的长度。仅适用于POST请求

3

HTTP_COOKIE

以键和值对的形式返回设置的cookie。

4

HTTP_USER_AGENT

User-Agent请求标头字段包含有关发起请求的用户代理的信息。 Web浏览器的名称。

5

PATH_INFO

CGI脚本的路径。

6

QUERY_STRING

与GET方法请求一起发送的URL编码信息。

7

REMOTE_ADDR

发出请求的远程主机的IP地址。这对于记录日志或进行身份验证很有用。

8

REMOTE_HOST

发出请求的主机的标准名称。如果此信息不可用,则可以使用REMOTE_ADDR获取IR地址。

9

REQUEST_METHOD

发出请求的方法。最常见的方法是GET和POST。

10

SCRIPT_FILENAME

CGI脚本的完整路径。

11

SCRIPT_NAME

CGI脚本的名称。

12

SERVER_NAME

服务器的主机名或IP地址。

13

SERVER_SOFTWARE

服务器正在运行的软件的名称和版本。

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

#!/usr/bin/perl

print "Content-type: text/html\n\n";
print "<font size=+1>Environment</font>\n";
foreach (sort keys %ENV) {
   print "<b>$_</b>: $ENV{$_}<br>\n";
}

1;

引发"File Download"对话框?

有时,您希望提供一个options,使用户单击链接,该链接将向用户弹出"File Download"对话框,而不显示实际内容。这非常简单,可以通过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, "<FileName" );
while(read(FILE, $buffer, 100) ) {
   print("$buffer");
}

GET和POST方法

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

使用GET方法传递信息

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

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

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

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

您可以通过简单地将键和值对与任何URL串联来传递信息,也可以使用HTML <FORM>标记使用GET方法传递信息。

简单的URLExample:获取方法

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

http://www.learnfk.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 "<html>";
print "<head>";
print "<title>Hello - Second CGI Program</title>";
print "</head>";
print "<body>";
print "<h2>Hello $first_name $last_name - Second CGI Program</h2>";
print "</body>";
print "</html>";

1;

简单的FORMExample:GET方法

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

<FORM action = "/cgi-bin/hello_get.cgi" method = "GET">
First Name: <input type = "text" name = "first_name">  <br>

Last Name: <input type = "text" name = "last_name">
<input type = "submit" value = "Submit">
</FORM>

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

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 "<html>";
print "<head>";
print "<title>Hello - Second CGI Program</title>";
print "</head>";
print "<body>";
print "<h2>Hello $first_name $last_name - Second CGI Program</h2>";
print "</body>";
print "</html>";

1;

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

<FORM action = "/cgi-bin/hello_post.cgi" method = "POST">
First Name: <input type = "text" name = "first_name">  <br>

Last Name: <input type = "text" name = "last_name">

<input type = "submit" value = "Submit">
</FORM>

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

First Name:

Last Name:

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

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

<form action = "/cgi-bin/checkbox.cgi" method = "POST" target = "_blank">
<input type = "checkbox" name = "maths" value = "on"> Maths
<input type = "checkbox" name = "physics" value = "on"> Physics
<input type = "submit" value = "Select Subject">
</form>

该代码的输出是以下形式-

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 "<html>";
print "<head>";
print "<title>Checkbox - Third CGI Program</title>";
print "</head>";
print "<body>";
print "<h2> CheckBox Maths is : $maths_flag</h2>";
print "<h2> CheckBox Physics is : $physics_flag</h2>";
print "</body>";
print "</html>";

1;

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

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

<form action = "/cgi-bin/radiobutton.cgi" method = "POST" target = "_blank">
<input type = "radio" name = "subject" value = "maths"> Maths
<input type = "radio" name = "subject" value = "physics"> Physics
<input type = "submit" value = "Select Subject">
</form>

该代码的输出是以下形式-

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 "<html>";
print "<head>";
print "<title>Radio - Fourth CGI Program</title>";
print "</head>";
print "<body>";
print "<h2> Selected Subject is $subject</h2>";
print "</body>";
print "</html>";

1;

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

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

<form action = "/cgi-bin/textarea.cgi" method = "POST" target = "_blank">
<textarea name = "textcontent" cols = 40 rows = 4>
Type your text here...
</textarea>
<input type = "submit" value = "Submit">
</form>

该代码的输出是以下形式-

下面是 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 "<html>";
print "<head>";
print "<title>Text Area - Fifth CGI Program</title>";
print "</head>";
print "<body>";
print "<h2> Entered Text Content is $text_content</h2>";
print "</body>";
print "</html>";

1;

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

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

<form action = "/cgi-bin/dropdown.cgi" method = "POST" target = "_blank">
<select name = "dropdown">
<option value = "Maths" selected>Maths</option>
<option value = "Physics">Physics</option>
</select>
<input type = "submit" value = "Submit">
</form>

该代码的输出是以下形式-

下面是 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 "<html>";
print "<head>";
print "<title>Dropdown Box - Sixth CGI Program</title>";
print "</head>";
print "<body>";
print "<h2> Selected Subject is $subject</h2>";
print "</body>";
print "</html>";

1;

在CGI中使用Cookie

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

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

这个怎么运行

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

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

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

  • Domain-您站点的域名。

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

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

  • Name=Value-Cookie是以键和值对的形式设置和重新查看的。

设置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.learnfk.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的Example。

#!/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
点我分享笔记