当前位置:首页 » Perl » Perl CGI

Perl CGI

Perl CGI在线教程,CGI是什么? 学习例子,实例代码,CGI在线教程等

CGI是什么 ?

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

  • 维护NCSA和NCSA CGI规范定义CGI如下:

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

  • 目前的版本是CGI/1.1和CGI/1.2正在进行中。

网页浏览

要理解这个概念的CGI,让我们看看会发生什么,当我们点击一个超链接,浏览特定网页或URL。

  • 您的浏览器输入URL,即HTTP Web服务器请求的.文件名。

  • Web服务器将解析URL,并请求其中文件名,如果找到这个文件则发送回浏览器,否则发送一个错误消息,显示你所请求的是一个错误的文件。

  • Web浏览器从Web服务器响应,并显示接收到的文件或错误消息。

但是,它是可能的设置了HTTP服务器,所以,每当请求一个特定的目录中的一个文件的文件没有被发送回来;相反,它是执行一个程序,无论该程序的输出被发送回您的浏览器显示。这个函数被调用的通用网关接口CGI和程序称为CGI脚本。这些CGI程序可以是一个Perl脚本,shell脚本,C或C ++程序等。

CGI架构图

Web服务器支持与配置

在你进行CGI编程之前,请确保您的Web服务器支持CGI,它被配置为处理CGI程序。由HTTP服务器来执行所有的CGI程序保持在一个预先配置的目录。此目录被称为CGI目录,并按照约定,它被命名为/cgi-bin目录。通过惯例的PERL CGI文件扩展名为.cgi。

第一个CGI程序

下面是一个简单的链接,链接到CGI脚本称为hello.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 - First CGI Program</title>';
print '</head>';
print '<body>';
print '<h2>Hello Word! This is my first CGI program</h2>';
print '</body>';
print '</html>';

1;

If you click hello.cgi then this produces following output:

Hello Word! This is my first CGI program

hello.cgi 是一个简单的脚本,它在将STDOUT(标准输出)文件到IE屏幕。有一个重要的和额外的功能,这是要打印的第一行 Content-type:text/html\r\n\r\n. 这一行被发送回给浏览器,并指定该内容类型被显示在浏览器画面上。现在你必须理解CGI的基本概念,你可以使用PERL写很多复杂的CGI程序。这个脚本可以与任何其他外部系统交换信息,如RDBMS。

HTTP头

Content-type:text/html\r\n\r\n 这一行是HTTP头的一部分,这是发送给浏览器能理解的内容。所有的HTTP报头将在下面的表格

HTTP Field Name: Field Content

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

还有其他一些重要的HTTP报头,你将经常使用在CGI编程。


Header Description
Content-type: String A MIME string defining the format of the file being returned. Example is Content-type:text/html
Expires: Date String The date 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.
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 file.
Last-modified: String The date of last modification of the resource.
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.
Set-Cookie: String Set the cookie passed through the string

CGI 环境变量

所有的CGI程序,将有机会获得以下环境变量。这些变量中发挥了重要作用,当在编写任何CGI程序时。

Variable Name Description
CONTENT_TYPE The data type of the content. Used when the client is sending attached content to the server. For example file upload etc.
CONTENT_LENGTH The length of the query information. It's available only for POST requests
HTTP_COOKIE Return the set cookies in the form of key & value pair.
HTTP_USER_AGENT The User-Agent request-header field contains information about the user agent originating the request. Its name of the web browser.
PATH_INFO The path for the CGI script.
QUERY_STRING The URL-encoded information that is sent with GET method request.
REMOTE_ADDR The IP address of the remote host making the request. This can be useful for logging or for authentication purpose.
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.
REQUEST_METHOD The method used to make the request. The most common methods are GET and POST.
SCRIPT_FILENAME The full path to the CGI script.
SCRIPT_NAME The name of the CGI script.
SERVER_NAME The server's hostname or IP Address
SERVER_SOFTWARE The name and version of the software the server is running.

这里是小的CGI程序列出所有的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;

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

有时它需要一个使用就点击一个链接,你想给的选项,它会弹出一个“文件下载”对话框中的用户,这很容易将附件通过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方法发送编码的用户信息添加到页面请求。页页已编码的信息中分离由 '?' 字符如下:

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

GET方法是默认的方法来传递信息,从浏览器到Web服务器,它会产生一个很长的字符串出现在浏览器的位置:框中。不要使用GET方法,如果你有密码或其他敏感信息传递给服务器。GET方法有大小限制:只有1024个字符,可以在一个请求字符串。

这个信息被传递使用QUERY_STRING头和通过QUERY_STRING环境变量将在CGI的程序中访问。

您可以通过简单的连接键 - 值对的任何URL或传递信息,您可以使用HTML <FORM> 标签使用GET方法传递信息。

简单的URL:Get 方法

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

下面是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;

简单表单举例:GET方法

下面是一个简单的例子,通过两个值,使用HTML表单和提交按钮。我们将使用相同的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>

这是上述表单输入第一个和最后一个名称,然后单击“提交”按钮来查看结果。


使用POST方法传递信息:

一般信息传递给CGI程序更可靠的方法是POST方法。此程序包和GET方法方式相同地传递信息,但是,而不是将它作为一个文本字符串之后 ‘?’ 在URL中,它发送它作为一个单独的消息。此消息来自标准输入的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};
#by wwww.gitbook.net
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;

让我们再次以上面同样的例子,通过使用HTML表单和提交按钮的两个值。我们将要使用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>

这是上述表单的实际输出,输入第一个和最后一个名称,然后单击“提交”按钮来查看结果。


将复选框资料传递给CGI程序

复选框被使用时,须选择一个以上的选项。

下面是一个例子HTML代码的表单与这两个复选框。

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

这段代码的结果是下面的表格。

下面是checkbox.cgi脚本来处理网页浏览器输入单选按钮。

#!/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";
    }
#by www.gitbook.net
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程序

单选按钮用于当只有一个选项是必需的以便进行选择。

下面是一个例子的两个单选按钮的HTML代码:

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

下面是radiobutton.cgi脚本来处理网页浏览器输入单选按钮。

#!/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};
#by www.gitbook.net
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程序的文本区域的数据

TEXTAREA元素用于多行文本时,要传递给CGI程序。

下面是一个文本框的形式例如HTML代码:

<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};
#by www.gitbook.net
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程序

下拉框,当我们有很多可供选择,但只有一个或两个将被选中。

这里是一个下拉框的表单的HTML代码示例:

<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 : 这时候,Cookies设置键 - 值对的形式审查。

设置Cookie

这是很容易将cookie发送到浏览器。这些cookies将被一起发送的HTTP头。假设你要设置用户名和密码的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....

从这个例子中,你必须了解如何设置Cookie。我们使用的Set-Cookie HTTP标头设置cookie。

在这里它是可选的设置Cookie的属性,如过期,域和路径。值得注意的是,Cookie都设置在发送之前魔法线 "Content-type:text/html\r\n\r\n.

获取cookie

这是很容易检索的所有设置Cookie。Cookie是存储在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";

This will produce following result
User ID = XYZ
Password = XYZ123

CGI模块和库

你会发现很多在互联网上为您提供直接的功能,在你的CGI的程序中使用的内置模块。以下是重要的链接。