perl 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编程。


HeaderDescription
Content-type: StringA MIME string defining the format of the file being returned. Example is Content-type:text/html
Expires: Date StringThe 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 StringThe URL that should be returned instead of the URL requested. You can use this filed to redirect a request to any file.
Last-modified: StringThe date of last modification of the resource.
Content-length: StringThe length, in bytes, of the data being returned. The browser uses this value to report the estimated download time for a file.
Set-Cookie: StringSet the cookie passed through the string

CGI 环境变量

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

Variable NameDescription
CONTENT_TYPEThe data type of the content. Used when the client is sending attached content to the server. For example file upload etc.
CONTENT_LENGTHThe length of the query information. It's available only for POST requests
HTTP_COOKIEReturn the set cookies in the form of key & value pair.
HTTP_USER_AGENTThe User-Agent request-header field contains information about the user agent originating the request. Its name of the web browser.
PATH_INFOThe path for the CGI script.
QUERY_STRINGThe URL-encoded information that is sent with GET method request.
REMOTE_ADDRThe IP address of the remote host making the request. This can be useful for logging or for authentication purpose.
REMOTE_HOSTThe 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_METHODThe method used to make the request. The most common methods are GET and POST.
SCRIPT_FILENAMEThe full path to the CGI script.
SCRIPT_NAMEThe name of the CGI script.
SERVER_NAMEThe server's hostname or IP Address
SERVER_SOFTWAREThe 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.yiibai.com/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.yiibai.com
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.yiibai.com
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.yiibai.com
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.yiibai.com
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


A CGI script can be as simple or complex as you need it to be. It could be in Perl, Java, Python or any programming language. At it's core, a CGI application simply takes a request via HTTP (typically a web browser) and returns HTML. Let's look at a simple Hello World CGI script and break it down into it's simplest forms.

 #!/usr/bin/perl
 
 print "Content-type: text/html\n\n";
 print <<HTML;
 <html>
 <head>
 <title>A Simple Perl CGI</title>
 </head>
 <body>
 <h1>A Simple Perl CGI</h1>
 <p>Hello World</p>
 </body>
 HTML
 exit; 
If you run the program on the command line, you'll see that it does exactly what you'd expect. First it prints the Content-type line, then it prints the raw HTML. In order to see it in action in a web browser, you'll need to copy or upload the script to your web server and make sure the permissions are set correctly (chmod 755 on *nix systems). Once you've set it correctly, you should be able to browse to it and see the page displayed live on your server.

The key line is the first print statement:

 print "Content-type: text/html\n\n"; 
This tells the browser that the document coming after the two newlines is going to be HTML. You must send a header so the browser knows what type of document is coming next, and you must include a blank line between the header and the actual document.

Once the header is sent, it's just a matter of sending the HTML document itself. In the above example, we're using a here-doc to simplify printing a large chunk of plain text. Of course, this is really no different than having a plain HTML document sitting on your server. The real power of using a programming language like Perl to create your HTML comes when you add in some fancy Perl programming. In the next example, let's take part of our time and date script and put it in our web page.

 #!/usr/bin/perl
 
 @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
 @weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
 ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
 $year = 1900 + $yearOffset;
 $theTime = "$weekDays[$dayOfWeek] $months[$month] $dayOfMonth, $year";
 
 print "Content-type: text/html\n\n";
 print <<HTML;
 <html>
 <head>
 <title>A Simple Perl CGI</title>
 </head>
 <body>
 <h1>A Simple Perl CGI</h1>
 <p>$theTime</p>
 </body>
 HTML
 exit; 
This new CGI script will insert the current date into the page each time the script is called. In other words, it becomes a dynamic document that changes as the date changes, rather than a static document.

在网上的例子里面content-type: texxt/html\r\n\r\n,但是在linux里面是不是要用\n\n呢?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值