📅  最后修改于: 2020-12-23 05:01:34             🧑  作者: Mango
通用网关接口(CGI)是一组标准,用于定义Web服务器和自定义脚本之间如何交换信息。 CGI规范目前由NCSA维护。
通用网关接口(CGI)是外部网关程序与信息服务器(例如HTTP服务器)接口的标准。
当前版本是CGI / 1.1,CGI / 1.2正在开发中。
要了解CGI的概念,让我们看看单击超级链接浏览特定网页或URL时会发生什么。
您的浏览器联系HTTP Web服务器并要求提供URL,即文件名。
Web服务器解析URL并查找文件名。如果找到该文件,则将其发送回浏览器,否则发送一条错误消息,指示您请求了错误的文件。
Web浏览器从Web服务器获取响应,并显示接收到的文件或错误消息。
但是,可以设置HTTP服务器,以便每当请求某个目录中的文件时,该文件都不会被发回。而是将其作为程序执行,并将程序输出的所有内容发送回给浏览器显示。该函数称为通用网关接口或CGI,程序称为CGI脚本。这些CGI程序可以是Python脚本,PERL脚本,Shell脚本,C或C++程序等。
在继续进行CGI编程之前,请确保您的Web服务器支持CGI,并且已将其配置为处理CGI程序。 HTTP服务器要执行的所有CGI程序都保存在预先配置的目录中。该目录称为CGI目录,按照约定,其命名为/ var / www / cgi-bin。按照惯例,CGI文件的扩展名为。 cgi,但您也可以使用Python扩展名.py保留文件。
默认情况下,Linux服务器配置为仅运行/ var / www的cgi-bin目录中的脚本。如果要指定其他目录来运行CGI脚本,请在httpd.conf文件中注释以下行-
AllowOverride None
Options ExecCGI
Order allow,deny
Allow from all
Options All
在这里,我们假设您已成功启动并运行Web服务器,并且能够运行任何其他CGI程序,例如Perl或Shell等。
这是一个简单的链接,链接到一个名为hello.py的CGI脚本。该文件保存在/ var / www / cgi-bin目录中,并且具有以下内容。在运行CGI程序之前,请确保使用chmod 755 hello.py UNIX命令更改文件的模式,以使文件可执行。
#!/usr/bin/python
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 ('')
注意-脚本中的第一行必须是Python可执行文件的路径。在Linux中,它应该是#!/ usr / bin / python3
在浏览器中输入以下URL
http://localhost:8080/cgi-bin/hello.py
Hello Word! This is my first CGI program
这个hello.py脚本是一个简单的Python脚本,它将其输出写在STDOUT文件(即屏幕)上。有一个重要的额外功能可用,即要打印的第一行Content-type:text / html \ r \ n \ r \ n 。此行发送回浏览器,并指定要在浏览器屏幕上显示的内容类型。
到目前为止,您必须已经了解CGI的基本概念,并且可以使用Python编写许多复杂的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编程中将经常使用。
Sr.No. | Header & Description |
---|---|
1 |
Content-type: A MIME string defining the format of the file being returned. Example is Content-type:text/html |
2 |
Expires: Date The date the information becomes invalid. It is used by the browser to decide when a page needs to be refreshed. A valid date string is in the format 01 Jan 1998 12:00:00 GMT. |
3 |
Location: URL The URL that is returned instead of the URL requested. You can use this field to redirect a request to any file. |
4 |
Last-modified: Date The date of last modification of the resource. |
5 |
Content-length: N 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. | Variable Name & 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. |
2 |
CONTENT_LENGTH The length of the query information. It is 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. It is 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 is useful logging or for authentication. |
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程序,列出了所有CGI变量。单击此链接以查看结果获取环境
#!/usr/bin/python
import os
print ("Content-type: text/html\r\n\r\n");
print ("Environment");
for param in os.environ.keys():
print ("%20s: %s" % (param, os.environ[param]))
当您需要将一些信息从浏览器传递到Web服务器,最后传递给CGI程序时,您肯定遇到过很多情况。浏览器最常使用两种方法,两种将此信息传递到Web服务器。这些方法是GET方法和POST方法。
GET方法发送附加到页面请求的已编码用户信息。页面和编码信息由?分隔。字符如下-
http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2
GET方法是将信息从浏览器传递到Web服务器的默认方法,它会生成一个长字符串,该字符串将出现在浏览器的Location:框中。
如果您有密码或其他敏感信息要传递到服务器,请不要使用GET方法。
GET方法具有大小限制:请求字符串只能发送1024个字符。
GET方法使用QUERY_STRING标头发送信息,并且可以通过QUERY_STRING环境变量在CGI程序中进行访问。
您可以通过简单地将键和值对与任何URL串联来传递信息,也可以使用HTML
将信息传递到CGI程序的一种通常更可靠的方法是POST方法。这将以与GET方法完全相同的方式打包信息,但不是在?之后将其作为文本字符串发送。在网址中将其作为单独的消息发送。该消息以标准输入的形式进入CGI脚本。
下面是处理GET和POST方法的相同hello_get.py脚本。
#!/usr/bin/python
# Import modules for CGI handling
import cgi, cgitb
# Create instance of FieldStorage
form = cgi.FieldStorage()
# Get data from fields
first_name = form.getvalue('first_name')
last_name = form.getvalue('last_name')
print "Content-type:text/html\r\n\r\n"
print ""
print ""
print "Hello - Second CGI Program "
print ""
print ""
print "Hello %s %s
" % (first_name, last_name)
print ""
print ""
让我们再次采用与上述相同的示例,该示例使用HTML FORM和Submit按钮传递两个值。我们使用相同的CGI脚本hello_get.py来处理此输入。
First Name:
Last Name:
这是上面表格的实际输出。您输入名字和姓氏,然后单击提交按钮以查看结果。
当需要选择多个选项时,将使用复选框。
这是带有两个复选框的表单的示例HTML代码-
Maths
Physics
此代码的结果是以下形式-
以下是checkbox.cgi脚本,用于处理Web浏览器为复选框按钮提供的输入。
#!/usr/bin/python
# Import modules for CGI handling
import cgi, cgitb
# Create instance of FieldStorage
form = cgi.FieldStorage()
# Get data from fields
if form.getvalue('maths'):
math_flag = "ON"
else:
math_flag = "OFF"
if form.getvalue('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 : %s
" % math_flag
print " CheckBox Physics is : %s
" % physics_flag
print ""
print ""
当只需要选择一个选项时,使用单选按钮。
这是带有两个单选按钮的表单的示例HTML代码-
Maths
Physics
此代码的结果是以下形式-
以下是radiobutton.py脚本,用于处理Web浏览器为单选按钮提供的输入-
#!/usr/bin/python
# Import modules for CGI handling
import cgi, cgitb
# Create instance of FieldStorage
form = cgi.FieldStorage()
# Get data from fields
if form.getvalue('subject'):
subject = form.getvalue('subject')
else:
subject = "Not set"
print "Content-type:text/html\r\n\r\n"
print ""
print ""
print "Radio - Fourth CGI Program "
print ""
print ""
print " Selected Subject is %s
" % subject
print ""
print ""
当必须将多行文本传递给CGI程序时,将使用TEXTAREA元素。
这是带有TEXTAREA框的表单的示例HTML代码-
此代码的结果是以下形式-
下面是textarea.cgi脚本,用于处理Web浏览器给出的输入-
#!/usr/bin/python
# Import modules for CGI handling
import cgi, cgitb
# Create instance of FieldStorage
form = cgi.FieldStorage()
# Get data from fields
if form.getvalue('textcontent'):
text_content = form.getvalue('textcontent')
else:
text_content = "Not entered"
print "Content-type:text/html\r\n\r\n"
print ""
print "";
print "Text Area - Fifth CGI Program "
print ""
print ""
print " Entered Text Content is %s
" % text_content
print ""
当我们有许多可用选项但仅会选择一个或两个时,将使用下拉框。
这是带有一个下拉框的表单的示例HTML代码-
此代码的结果是以下形式-
以下是dropdown.py脚本,用于处理Web浏览器给出的输入。
#!/usr/bin/python
# Import modules for CGI handling
import cgi, cgitb
# Create instance of FieldStorage
form = cgi.FieldStorage()
# Get data from fields
if form.getvalue('dropdown'):
subject = form.getvalue('dropdown')
else:
subject = "Not entered"
print "Content-type:text/html\r\n\r\n"
print ""
print ""
print "Dropdown Box - Sixth CGI Program "
print ""
print ""
print " Selected Subject is %s
" % subject
print ""
print ""
HTTP协议是无状态协议。对于商业网站,需要在不同页面之间维护会话信息。例如,一个用户注册在完成许多页面后结束。如何在所有网页上维护用户的会话信息?
在许多情况下,使用Cookie是记住和跟踪偏好,购买,佣金和其他信息(以获得更好的访问者体验或站点统计信息所需)的最有效方法。
您的服务器以cookie的形式向访问者的浏览器发送一些数据。浏览器可以接受该cookie。如果是这样,它将作为纯文本记录存储在访问者的硬盘上。现在,当访问者到达您网站上的另一个页面时,就可以检索该cookie。一旦检索到,您的服务器就知道/记住存储了什么。
Cookies是5个可变长度字段的纯文本数据记录-
过期-Cookie过期的日期。如果为空,则cookie将在访问者退出浏览器时过期。
域-您站点的域名。
路径-设置cookie的目录或网页的路径。如果要从任何目录或页面检索cookie,则该字段可以为空白。
安全-如果此字段包含“安全”一词,则只能使用安全服务器检索cookie。如果此字段为空白,则不存在此类限制。
名称=值-Cookies以键和值对的形式设置和检索。
将cookie发送到浏览器非常容易。这些cookie与HTTP标头一起发送到Content-type字段。假设您要将UserID和Password设置为cookie。设置cookie的步骤如下-
#!/usr/bin/python
print "Set-Cookie:UserID = XYZ;\r\n"
print "Set-Cookie:Password = XYZ123;\r\n"
print "Set-Cookie:Expires = Tuesday, 31-Dec-2007 23:12:40 GMT;\r\n"
print "Set-Cookie:Domain = www.tutorialspoint.com;\r\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属性,例如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/python
# Import modules for CGI handling
from os import environ
import cgi, cgitb
if environ.has_key('HTTP_COOKIE'):
for cookie in map(strip, split(environ['HTTP_COOKIE'], ';')):
(key, value ) = split(cookie, '=');
if key == "UserID":
user_id = value
if key == "Password":
password = value
print "User ID = %s" % user_id
print "Password = %s" % password
这将为上述脚本设置的cookie产生以下结果-
User ID = XYZ
Password = XYZ123
要上传文件,HTML表单必须将enctype属性设置为multipart / form-data 。具有文件类型的输入标签将创建一个“浏览”按钮。
File:
此代码的结果是以下形式-
文件:
上面的示例已被有意地禁用,以防止人们在我们的服务器上上传文件,但是您可以在服务器上尝试上述代码。
这是脚本save_file.py来处理文件上传-
#!/usr/bin/python
import cgi, os
import cgitb; cgitb.enable()
form = cgi.FieldStorage()
# Get filename here.
fileitem = form['filename']
# Test if the file was uploaded
if fileitem.filename:
# strip leading path from file name to avoid
# directory traversal attacks
fn = os.path.basename(fileitem.filename)
open('/tmp/' + fn, 'wb').write(fileitem.file.read())
message = 'The file "' + fn + '" was uploaded successfully'
else:
message = 'No file was uploaded'
print """\
Content-Type: text/html\n
%s
""" % (message,)
如果您在Unix / Linux上运行上述脚本,则需要注意按以下步骤替换文件分隔符,否则在Windows机器上的open()语句应该可以正常工作。
fn = os.path.basename(fileitem.filename.replace("\\", "/" ))
有时,希望您提供用户可以单击链接的选项,它将向用户弹出“文件下载”对话框,而不显示实际内容。这非常简单,可以通过HTTP标头实现。这个HTTP标头与上一节中提到的标头不同。
例如,如果要使FileName文件可从给定链接下载,则其语法如下-
#!/usr/bin/python
# 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 here.
fo = open("foo.txt", "rb")
str = fo.read();
print str
# Close opend file
fo.close()
希望您喜欢本教程。如果是,请通过以下方式向我发送您的反馈意见:与我们联系