📅  最后修改于: 2020-10-16 05:42:16             🧑  作者: Mango
通用网关接口(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编程之前,请确保您的Web服务器支持CGI功能并将其配置为处理CGI程序。 Web服务器要执行的所有CGI程序都保存在预先配置的目录中。该目录称为CGI目录,按照约定,其命名为/ cgi-bin。按照约定,Perl 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服务或任何其他复杂的界面。
第一行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程序时都起着重要作用。
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, "
当您需要将一些信息从浏览器传递到Web服务器,并最终传递给处理您的请求的CGI程序时,您肯定遇到过许多情况。浏览器最经常使用两种方法将此信息传递到Web服务器。这些方法是GET方法和POST方法。让我们一一检查。
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
姓:
将信息传递到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:
这是上述表单编码的实际输出,您输入名和姓,然后单击提交按钮以查看结果。
姓:
当需要选择多个选项时,将使用复选框。这是带有两个复选框的表单的示例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;
当只需要选择一个选项时,使用单选按钮。这是带有两个单选按钮的表单的示例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程序时,将使用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;
当我们有许多可用选项,但只选择一个或两个时,将使用一个下拉框。这是带有一个下拉框的表单的示例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;
HTTP协议是无状态协议。但是对于商业网站,需要在不同页面之间维护会话信息。例如,一个用户注册在跨越多个页面的交易之后结束。但是,如何在所有网页上维护用户的会话信息?
在许多情况下,使用Cookie是记住和跟踪偏好,购买,佣金和其他信息(以获得更好的访问者体验或站点统计信息所需)的最有效方法。
您的服务器以cookie的形式向访问者的浏览器发送一些数据。浏览器可以接受该cookie。如果是这样,它将以纯文本记录的形式存储在访问者的硬盘上。现在,当访问者到达您网站上的另一个页面时,就可以检索该cookie。一旦检索到,您的服务器就知道/记住存储了什么。
Cookies是5个可变长度字段的纯文本数据记录-
过期-Cookie过期的日期。如果为空,则cookie将在访问者退出浏览器时过期。
域-您站点的域名。
路径-设置cookie的目录或网页的路径。如果要从任何目录或页面检索cookie,则该字段可以为空白。
安全-如果此字段包含“安全”一词,则只能使用安全服务器检索cookie。如果此字段为空白,则不存在此类限制。
名称=值-Cookies以键和值对的形式设置和重新查看。
将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非常容易。 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
您会在Internet上找到许多内置模块,这些模块为您提供了直接功能,可以在CGI程序中使用。以下是重要的一次。