通用网关接口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,它被配置为处理CGI程序。由HTTP服务器来执行所有的CGI程序保持在一个预先配置的目录。此目录被称为CGI目录,并按照约定,它被命名为/cgi-bin目录。通过惯例的PERL 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。
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程序时。
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"); }
可能所遇到的有很多情况,如,你需要从您的浏览器传递一些信息到Web服务器并最终到达CGI程序。最常见的浏览器使用两种方法将此信息传递到Web服务器。这些方法是GET方法和POST方法。
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将传递两个值,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;
下面是一个简单的例子,通过两个值,使用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>
这是上述表单输入第一个和最后一个名称,然后单击“提交”按钮来查看结果。
一般信息传递给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>
这是上述表单的实际输出,输入第一个和最后一个名称,然后单击“提交”按钮来查看结果。
复选框被使用时,须选择一个以上的选项。
下面是一个例子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;
单选按钮用于当只有一个选项是必需的以便进行选择。
下面是一个例子的两个单选按钮的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;
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;
下拉框,当我们有很多可供选择,但只有一个或两个将被选中。
这里是一个下拉框的表单的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;
HTTP协议是无状态协议。但对于一个商业网站,它需要不同的页面之间维护会话信息。例如,一个用户注册结束后完成了许多网页。但如何保持用户的会话信息在所有的网页。
在许多情况下,使用Cookie的记忆和跟踪的喜好,购买,佣金是最有效的方法,更好的访问者的体验或网站的统计和其他所需的信息。
你的服务器发送一些数据到访问者的浏览器的cookie的形式。浏览器可能会接受Cookie。如果是的话,它被存储在访问者的硬盘驱动器作为一个普通的文字记录。现在,当访问者到达您的网站的另一个页面上,cookie是可用于检索。一旦检索完毕,您的服务器知道/记忆存储。
Cookies是一个纯文本的5个可变长度字段的数据记录:
Expires : cookie将到期的日期。如果是空白的,当访问者退出浏览器,cookie将到期。
Domain : 您的网站的域名。
Path : 目录或网页设置cookie的路径。这可能是空白的,如果你想从任何目录或页面来检索该cookie。
Secure : 如果此字段中包含单词“安全”的cookie可能只能与一个安全的服务器中检索。如果该字段为空,不存在这样的限制。
Name=Value : 这时候,Cookies设置键 - 值对的形式审查。
这是很容易将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是存储在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的程序中使用的内置模块。以下是重要的链接。