May 10, 2021 Python2
CGI is currently maintained by NCSA, which defines CGI as follows:
CGI (Common Gateway Interface), a common gateway interface, is a program that runs on a server such as an HTTP server and provides an interface with a client HTML page.
To better understand how CGI works, we can click on a link or URL on a Web page:
CGI programs can be Python scripts, PERL scripts, SHELL scripts, C or C?programs, etc.
Before you program CGI, make sure that your web server supports CGI and that CGI handlers are configured.
Apache supports CGI configurations:
Set up the CGI directory:
ScriptAlias /cgi-bin/ /var/www/cgi-bin/
All HTTP server execution CGI programs are stored in a pre-configured directory. This directory is called the CGI directory, and as a rule, it is named /var/www/cgi-bin directory.
The extension of the CGI file .cgi, and Python can also use .py extension.
By default, the Linux server configuration runs in the cgi-bin directory /var/www.
If you want to specify other directories that run CGI scripts, you can modify the httpd.conf profile as follows:
<Directory "/var/www/cgi-bin">
AllowOverride None
Options +ExecCGI
Order allow,deny
Allow from all
</Directory>
Add the suffix .py AddHandler so that we can access .py Python script file at the end of the file:
AddHandler cgi-script .cgi .pl .py
We used Python to create the first CGI program with the file name hellp.py, which is located in the /var/www/cgi-bin directory and is as follows, with permission to modify the file to 755:
#coding=utf-8
#!/usr/bin/python
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>'
The above programs display the following results in browser access:
Hello Word! This is my first CGI program
This hello.py script is a simple Python script, the first line of the script output "Content-type:text/html\r\n" sent to the browser and informed the browser that the content type displayed is "text/html".
hello.py "Content-type:text/html\n" in the contents of the file is part of the HTTP header, which is sent to the browser to tell the browser the content type of the file.
The format of the HTTP header is as follows:
HTTP 字段名: 字段内容
For example:
Content-type: text/html
The following table describes the information that http heads are frequently used in CGI programs:
Head | Describe |
---|---|
Content-type: | The requested MIME information corresponding to the entity. For example: Content-type:text/html |
Expires: Date | The date and time the response expired |
Location: URL | Used to redirect the receiver to a location that is not a request URL to complete the request or identify a new resource |
Last-modified: Date | The last time the resource was requested to be modified |
Content-length: N | The length of the requested content |
Set-Cookie: String | Set an Http cookie |
All CGI programs receive the following environmental variables, which play an important role in CGI programs:
The name of the variable | Describe |
---|---|
CONTENT_TYPE | The value of this environment variable indicates the type of MIME of the information passed. Currently, environment variables CONTENT_TYPE generally: application/x-www-form-urlencoded, which says the data comes from HTML forms. |
CONTENT_LENGTH | If the server and CGI program information is passed in a POST, this environment variable is even the number of bytes of valid data that can be read from the standard input STDIN. This environment variable must be used when reading the data entered. |
HTTP_COOKIE | The contents of the COOKIE within the client. |
HTTP_USER_AGENT | Provides customer browser information that contains the number of versions or other proprietary data. |
PATH_INFO | The value of this environment variable represents other path information immediately after the CGI program name. It often appears as a parameter of a CGI program. |
QUERY_STRING | If the server and CGI program information is delivered in a GET way, the value of this environment variable even if the information is passed. T his information is followed by the CGI program name, with a question mark between the two.???" Separated. |
REMOTE_ADDR | The value of this environment variable is the IP address of the client that sent the request, for example, 192.168.1.67 above. T his value is always present. And it is the unique identity that Web clients need to provide to Web servers, which you can use in CGI programs to distinguish between different Web clients. |
REMOTE_HOST | The value of this environment variable contains the host name of the client that sent the CGI request. If you do not support the query you want, you do not need to define this environment variable. |
REQUEST_METHOD | Provides the method to which the script is called. For scripts that use the HTTP/1.0 protocol, only GET and POST make sense. |
SCRIPT_FILENAME | The full path to the CGI script |
SCRIPT_NAME | The name of the CGI script |
SERVER_NAME | This is the host name, alias, or IP address of your WEB server. |
SERVER_SOFTWARE | The value of this environment variable contains the name and version number of the HTTP server that called the CGI program. For example, the above value is Apache/2.2.14 (Unix) |
Here's a simple CGI script that outputs CGI's environment variables:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# filename:test.py
import os
print "Content-type: text/html"
print
print "<meta charset=\"utf-8\">"
print "<b>环境变量</b><br>";
print "<ul>"
for key in os.environ.keys():
print "<li><span style='color:green'>%30s </span> : %s </li>" % (key,os.environ[key])
print "</ul>"
The browser client passes information to the server in two ways, the GET method and the POST method.
The GET method sends encoded user information to the service side, and the data information is included on the URL of the request page to " ? number split, as follows:
http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2
Some other comments about get requests:
Here's a simple URL that uses the GET method hello_get.py two parameters to the program:
/cgi-bin/hello_get.py?first_name=ZARA&last_name=ALI
Here's hello_get.py code for the file:
#coding=utf-8
#!/usr/bin/python
# CGI处理模块
import cgi, cgitb
# 创建 FieldStorage 的实例化
form = cgi.FieldStorage()
# 获取数据
first_name = form.getvalue('first_name')
last_name = form.getvalue('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 %s %s</h2>" % (first_name, last_name)
print "</body>"
print "</html>"
The browser requests the output:
Hello ZARA ALI
The following is a form that uses the GET method to send two data to the server using the GET method, and the submitted server script is also hello_get.py file, code as follows:
<form action="/cgi-bin/hello_get.py" 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>
Using the POST method to pass data to the server is more secure and reliable, as sensitive information such as user passwords requires the use of POST to transfer data.
The following is also hello_get.py, which can also handle POST form data submitted by the browser:
#coding=utf-8
#!/usr/bin/python
# 引入 CGI 模块
import cgi, cgitb
# 创建 FieldStorage 实例
form = cgi.FieldStorage()
# 获取表单数据
first_name = form.getvalue('first_name')
last_name = form.getvalue('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 %s %s</h2>" % (first_name, last_name)
print "</body>"
print "</html>"
The following is the form that submits data to the server hello_get.py the POST method:
<form action="/cgi-bin/hello_get.py" 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>
Checkbox is used to submit one or more option data, and the HTML code is as follows:
<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>
Here's the code .cgi checkbox file:
#coding=utf-8
#!/usr/bin/python
# 引入 CGI 处理模块
import cgi, cgitb
# 创建 FieldStorage的实例
form = cgi.FieldStorage()
# 接收字段数据
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 "<html>"
print "<head>"
print "<title>Checkbox - Third CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> CheckBox Maths is : %s</h2>" % math_flag
print "<h2> CheckBox Physics is : %s</h2>" % physics_flag
print "</body>"
print "</html>"
Radio passes only one data to the server, and the HTML code looks like this:
<form action="/cgi-bin/radiobutton.py" 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.py script code is as follows:
#coding=utf-8
#!/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 "<html>"
print "<head>"
print "<title>Radio - Fourth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"
Textarea passes multiple lines of data to the server, and the HTML code is as follows:
<form action="/cgi-bin/textarea.py" method="post" target="_blank">
<textarea name="textcontent" cols="40" rows="4">
Type your text here...
</textarea>
<input type="submit" value="Submit" />
</form>
The textarea .cgi script code as follows:
#coding=utf-8
#!/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 "<html>"
print "<head>";
print "<title>Text Area - Fifth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Entered Text Content is %s</h2>" % text_content
print "</body>"
The HTML pull-down box code is as follows:
<form action="/cgi-bin/dropdown.py" 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.py script code looks like this:
#coding=utf-8
#!/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 "<html>"
print "<head>"
print "<title>Dropdown Box - Sixth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"
One of the great disadvantages of the http protocol is that it does not judge the user's identity, which is a great inconvenience to programmers.
The emergence of cookies makes up for this deficiency.
All cookies are the customer access script at the same time, through the customer's browser, the customer's hard disk to write record data, the next time the customer accesses the script to get back the data information, so as to achieve the function of identity identification, cookies are often used in password judgment.
The http cookie is sent via the http header, which predations the transmission of the file, and the syntax of the head set-cookie is as follows:
Set-cookie:name=name;expires=date;path=path;domain=domain;secure
Cookies are set up very simply and are sent separately at the http header. The following instances have UserID and Password set in the cookie:
<pre>
#coding=utf-8
#!/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.w3cschool.cn;\r\n"
print "Set-Cookie:Path=/perl;\n"
print "Content-type:text/html\r\n\r\n"
...........Rest of the HTML Content....
The above example uses set-cookie header information to set cookie information, and other properties of cookies, such as Expiration Time Expires, Domain Domain, Path Path, can be selected. T his information is set before "Content-type:text/html\n\n?n".
The cookie information retrieval page is very simple and the cookie information is stored in CGI's environment HTTP_COOKIE, in the following format:
key1=value1;key2=value2;key3=value3....
Here's a simple CGI program for retrieving cookie information:
#coding=utf-8
#!/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
The output of the above script is as follows:
User ID = XYZ
Password = XYZ123
File upload instance:
HTML Settings The form for uploading files needs to set the enctype property to multipart/form-data, as follows:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>w3cschool教程(w3cschool.cn)</title>
</head>
<body>
<form enctype="multipart/form-data" action="/cgi-bin/save_file.py" method="post">
<p>选中文件: <input type="file" name="filename" /></p>
<p><input type="submit" value="上传" /></p>
</form>
</body>
</html>
save_file.py script file code is as follows:
#coding=utf-8
#!/usr/bin/python
import cgi, os
import cgitb; cgitb.enable()
form = cgi.FieldStorage()
# 获取文件名
fileitem = form['filename']
# 检测文件是否上传
if fileitem.filename:
# 设置文件路径
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
<html>
<body>
<p>%s</p>
</body>
</html>
""" % (message,)
If you're using Unix/Linux, you have to replace the file separator, just use the open() statement under window:
fn = os.path.basename(fileitem.filename.replace("\\", "/" ))
If we need to provide the user with a file download link and pop up the file download dialog box after the user clicks on the link, we do so by setting up http header information, which is coded as follows:
#coding=utf-8
#!/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 hear.
fo = open("foo.txt", "rb")
str = fo.read();
print str
# Close opend file
fo.close()