Python CGI programming



What is CGI

CGI is currently maintained by NCSA. NCSA defines CGI as follows:

CGI (Common Gateway Interface), common gateway interface, it is a program , runs on the server such as: HTTP server, providing an interface with the client HTML page.


Web browsing

In order to better understand how CGI works, we can start with the process of clicking a link or URL on a web page:

  • 1. Use your browser to access the URL and connect to the HTTP web server.

  • 2. After receiving the request information, the web server will parse the URL and check whether the accessed file exists on the server. If the file exists, it will return the content of the file, otherwise it will return an error message.

  • 3. The browser receives information from the server and displays the received file or error message.

CGI program can be a Python script, PERL script, SHELL script, C or C++ program, etc.


CGI architecture diagram

1026.png


Web server support and configuration

Before you perform CGI programming, make sure you The web server supports CGI and has CGI handlers configured.

Apache supports CGI configuration:

Set the CGI directory:

ScriptAlias /cgi-bin/ /var/www/cgi-bin/

All HTTP server execution CGI programs are saved in a pre-configured directory. This directory is called the CGI directory, and by convention, it is named /var/www/cgi-bin.

The extension of CGI files is .cgi, and python can also use the .py extension.

By default, the cgi-bin directory where the Linux server is configured to run is /var/www.

If you want to specify other directories for running CGI scripts, you can modify the httpd.conf configuration file as follows:

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options +ExecCGI
   Order allow,deny
   Allow from all
</Directory>

Add the .py suffix in AddHandler so that we can access it. python script file ending with py:

AddHandler cgi-script .cgi .pl .py

The first CGI program

We use Python to create the first CGI program. The file name is hello.py and the file is located in /var/ In the www/cgi-bin directory, the content is as follows:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

print "Content-type:text/html"
print                               # 空行,告诉服务器结束头部
print '<html>'
print '<head>'
print '<meta charset="utf-8">'
print '<title>Hello Word - 我的第一个 CGI 程序!</title>'
print '</head>'
print '<body>'
print '<h2>Hello Word! 我是来自php中文网的第一CGI程序</h2>'
print '</body>'
print '</html>'

After saving the file, modify hello.py and modify the file permissions to 755:

chmod 755 hello.py

When the above program is accessed in the browser, the result is as follows:

1026.jpg

This hello.py script is a simple Python script. The output content of the first line of the script "Content-type: text/html" is sent to the browser and informs the browser The content type displayed by the browser is "text/html".

Use print to output a blank line to tell the server to end the header information.


HTTP header

The "Content-type:text/html" in the content of the hello.py file is part of the HTTP header, which will be sent to the browser to tell the browser The content type of the server file.

The format of the HTTP header is as follows:

HTTP 字段名: 字段内容

For example:

Content-type: text/html

The following table introduces the information commonly used in HTTP headers in CGI programs:

HeaderDescription
Content-type:The requested MIME information corresponding to the entity . For example: Content-type:text/html
Expires: DateThe date and time the response expires
Location: URL is used to redirect the recipient to a non-requested URL to complete the request or identify a new resource
Last-modified: Date The last modification time of the requested resource
Content-length: NThe requested content length
Set-Cookie: String Set Http Cookie

CGI Environment Variables

All CGI programs receive the following environment variables, which are Plays an important role in CGI programs:

##Variable nameDescription##CONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_USER_AGENTPATH_INFOQUERY_STRINGREMOTE_ADDRREMOTE_HOSTREQUEST_METHODSCRIPT_FILENAMESCRIPT_NAMESERVER_NAMESERVER_SOFTWARE

The following is a simple CGI script to output CGI 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>"

Save the above points as test.py, and modify the file permissions to 755. The execution results are as follows:

1027.jpg


GET and POST methods

The browser client passes information to the server through two methods, the two methods are the GET method and the POST method.

Use the GET method to transmit data

The GET method sends the encoded user information to the server. The data information is included in the URL of the request page, separated by "?", as shown below:

http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2
Some other notes about GET requests:
  • GET requests can be cached

  • GET requests remain in browser history

  • GET requests can be bookmarked

  • GET requests should not be used when handling sensitive data

  • GET requests have length limits

  • GET requests should only be used to retrieve data

Simple url example: GET method

The following is a simple URL that uses the GET method to send two parameters to the hello_get.py program:

/cgi-bin/test.py?name=php中文网&url=//m.sbmmt.com

The following is the code for the hello_get.py file:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# filename:test.py

# CGI处理模块
import cgi, cgitb 

# 创建 FieldStorage 的实例化
form = cgi.FieldStorage() 

# 获取数据
site_name = form.getvalue('name')
site_url  = form.getvalue('url')

print "Content-type:text/html"
print
print "<html>"
print "<head>"
print "<meta charset=\"utf-8\">"
print "<title>php中文网 CGI 测试实例</title>"
print "</head>"
print "<body>"
print "<h2>%s官网:%s</h2>" % (site_name, site_url)
print "</body>"
print "</html>"

Modify hello_get after saving the file. py, modify the file permission to 755:

chmod 755 hello_get.py

Browser request output result:

1028.jpg

Simple form example: GET method

The following It is an HTML form that uses the GET method to send two data to the server. The submitted server script is also the hello_get.py file. The hello_get.html code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/hello_get.py" method="get">
站点名称: <input type="text" name="name">  <br />

站点 URL: <input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>

By default, the cgi-bin directory can only be stored For the script file, we store hello_get.html in the test directory and modify the file permissions to 755:

chmod 755 hello_get.html

Gif The demo is as follows:

hello_get.gif

Use POST Method to transfer data

Using the POST method to transfer data to the server is more secure and reliable. Some sensitive information such as user passwords need to use POST to transfer data.

The following is hello_get.py, which can also process POST form data submitted by the browser:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# CGI处理模块
import cgi, cgitb 

# 创建 FieldStorage 的实例化
form = cgi.FieldStorage() 

# 获取数据
site_name = form.getvalue('name')
site_url  = form.getvalue('url')

print "Content-type:text/html"
print
print "<html>"
print "<head>"
print "<meta charset=\"utf-8\">"
print "<title>php中文网 CGI 测试实例</title>"
print "</head>"
print "<body>"
print "<h2>%s官网:%s</h2>" % (site_name, site_url)
print "</body>"
print "</html>"

The following is the form through the POST method (method="post" ) Submit data to the server script hello_get.py:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/hello_get.py" method="post">
站点名称: <input type="text" name="name">  <br />

站点 URL: <input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>

Gif demonstration is as follows:

hello_post.gif

Transfer checkbox data through CGI program

Checkbox is used to submit one or more option data. The HTML code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/checkbox.py" method="POST" target="_blank">
<input type="checkbox" name="php" value="on" /> php中文网
<input type="checkbox" name="google" value="on" /> Google
<input type="submit" value="选择站点" />
</form>
</body>
</html>

The following is the code of the checkbox.py file:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# 引入 CGI 处理模块 
import cgi, cgitb 

# 创建 FieldStorage的实例 
form = cgi.FieldStorage() 

# 接收字段数据
if form.getvalue('google'):
   google_flag = "是"
else:
   google_flag = "否"

if form.getvalue('php'):
   php_flag = "是"
else:
   php_flag = "否"

print "Content-type:text/html"
print
print "<html>"
print "<head>"
print "<meta charset=\"utf-8\">"
print "<title>php中文网 CGI 测试实例</title>"
print "</head>"
print "<body>"
print "<h2> php中文网是否选择了 : %s</h2>" % php_flag
print "<h2> Google 是否选择了 : %s</h2>" % google_flag
print "</body>"
print "</html>"

Modify checkbox.py permissions:

chmod 755 checkbox.py

Browser access Gif demonstration:

checkbox.gif

Transfer Radio data through CGI program

Radio only delivers one data to the server, the HTML code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/radiobutton.py" method="post" target="_blank">
<input type="radio" name="site" value="php" /> php中文网
<input type="radio" name="site" value="google" /> Google
<input type="submit" value="提交" />
</form>
</body>
</html>

radiobutton.py The script code is as follows:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# 引入 CGI 处理模块 
import cgi, cgitb 

# 创建 FieldStorage的实例 
form = cgi.FieldStorage() 

# 接收字段数据
if form.getvalue('site'):
   site = form.getvalue('site')
else:
   site = "提交数据为空"

print "Content-type:text/html"
print
print "<html>"
print "<head>"
print "<meta charset=\"utf-8\">"
print "<title>php中文网 CGI 测试实例</title>"
print "</head>"
print "<body>"
print "<h2> 选中的网站是 %s</h2>" % site
print "</body>"
print "</html>"

Modify radiobutton .py permissions:

chmod 755 radiobutton.py

Browser access to Gif Demo picture:

radiobutton.gif

Transfer Textarea data through CGI program

Textarea transfers multiple messages to the server Row data, HTML code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/textarea.py" method="post" target="_blank">
<textarea name="textcontent" cols="40" rows="4">
在这里输入内容...
</textarea>
<input type="submit" value="提交" />
</form>
</body>
</html>

textarea.py Script code is as follows:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# 引入 CGI 处理模块 
import cgi, cgitb 

# 创建 FieldStorage的实例 
form = cgi.FieldStorage() 

# 接收字段数据
if form.getvalue('textcontent'):
   text_content = form.getvalue('textcontent')
else:
   text_content = "没有内容"

print "Content-type:text/html"
print
print "<html>"
print "<head>";
print "<meta charset=\"utf-8\">"
print "<title>php中文网 CGI 测试实例</title>"
print "</head>"
print "<body>"
print "<h2> 输入的内容是:%s</h2>" % text_content
print "</body>"
print "</html>"

Modify textarea.py Permissions:

chmod 755 textarea.py

Browser access Gif demo image:

textarea.gif

Pass drop-down data through CGI program.

HTML drop-down box code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/dropdown.py" method="post" target="_blank">
<select name="dropdown">
<option value="php" selected>php中文网</option>
<option value="google">Google</option>
</select>
<input type="submit" value="提交"/>
</form>
</body>
</html>

dropdown.py script code is as follows:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# 引入 CGI 处理模块 
import cgi, cgitb 

# 创建 FieldStorage的实例 
form = cgi.FieldStorage() 

# 接收字段数据
if form.getvalue('dropdown'):
   dropdown_value = form.getvalue('dropdown')
else:
   dropdown_value = "没有内容"

print "Content-type:text/html"
print
print "<html>"
print "<head>"
print "<meta charset=\"utf-8\">"
print "<title>php中文网 CGI 测试实例</title>"
print "</head>"
print "<body>"
print "<h2> 选中的选项是:%s</h2>" % dropdown_value
print "</body>"
print "</html>"

Modify dropdown.py permissions:

chmod 755 dropdown.py

Browser Visit Gif demo image:

dropdown.gif


Using Cookies in CGI

A big shortcoming of the http protocol is that it does not judge the user’s identity. It brings great inconvenience to programmers. The emergence of the cookie function makes up for this shortcoming.

Cookie is to write record data on the customer's hard drive through the customer's browser while the customer accesses the script. , the data information will be retrieved the next time the customer accesses the script, so as to achieve the function of identity discrimination. Cookies are often used in identity verification.

 

Cookie syntax

http cookie is sent through the http header, which is earlier than the file transfer. The syntax of the set-cookie header is as follows:

Set-cookie:name=name;expires=date;path=path;domain=domain;secure
  • name=name: You need to set the cookie value (name cannot use ";" and ","), how many Use ";" to separate name values, for example: name1=name1;name2=name2;name3=name3.

  • expires=date: Cookie validity period, format: expires="Wdy,DD-Mon-YYYY HH:MM:SS"


  • path=path: Set the path supported by cookies. If path is a path, the cookie will be in this directory. Valid for all files and subdirectories, for example: path="/cgi-bin/". If path is a file, the cookie will be valid for this file, for example: path="/cgi-bin/cookie.cgi".

  • domain=domain: Domain name that is valid for cookies, for example: domain="m.sbmmt.com"

  • secure: If this flag is given, it means that the cookie can only be passed through the https server of the SSL protocol.

  • The reception of cookies is achieved by setting the environment variable HTTP_COOKIE. CGI programs can obtain cookie information by retrieving this variable.


Cookie Settings

Cookie setting is very simple, the cookie will be sent separately in the http header. The following example sets the name and expires in the cookie:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 
print 'Content-Type: text/html'
print 'Set-Cookie: name="php中文网";expires=Wed, 28 Aug 2016 18:30:00 GMT'
print
print """
<html>
	<head>
		<meta charset="utf-8">
		<title>php中文网(php.cn)</title>
	</head>
    <body>
        <h1>Cookie set OK!</h1>
    </body>
</html>
"""

Save the above code to cookie_set.py, and modify the cookie_set.py permissions:

chmod 755 cookie_set.py

The above example uses the Set-Cookie header information To set Cookie information, other attributes of Cookie are set in the optional options, such as expiration time Expires, domain name, and path. This information is set before "Content-type:text/html".


Retrieve Cookie information

The Cookie information retrieval page is very simple. Cookie information is stored in the CGI environment variable HTTP_COOKIE. The storage format is as follows:

key1=value1;key2=value2;key3=value3....

The following is a Simple CGI program to retrieve cookie information:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# 导入模块
import os
import Cookie

print "Content-type: text/html"
print

print """
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<h1>读取cookie信息</h1>
"""

if 'HTTP_COOKIE' in os.environ:
    cookie_string=os.environ.get('HTTP_COOKIE')
    c=Cookie.SimpleCookie()
    c.load(cookie_string)

    try:
        data=c['name'].value
        print "cookie data: "+data+"<br>"
    except KeyError:
        print "cookie 没有设置或者已过去<br>"
print """
</body>
</html>

"""

Save the above code to cookie_get.py, and modify cookie_get.py permissions:

chmod 755 cookie_get.py

The above cookie setting color Gif is as follows:

cookie.gif

File upload example

HTML setting form for uploading files needs to set the enctype attribute to multipart/form-data , the code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.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:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

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 = '文件 "' + fn + '" 上传成功'
   
else:
   message = '文件没有上传'
   
print """\
Content-Type: text/html\n
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
   <p>%s</p>
</body>
</html>
""" % (message,)

Save the above code to save_file.py, and modify save_file.py permissions:

chmod 755 save_file.py

The above cookie setting color Gif is as follows:

savefile.gif

If the system you are using is Unix/Linux, you must replace the file separator. Under window, you only need to use open( ) statement:

fn = os.path.basename(fileitem.filename.replace("\", "/" ))

File download dialog box

We first create the foo.txt file in the current directory for downloading the program.

File downloading is achieved by setting HTTP header information. The function code is as follows:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# HTTP 头部
print "Content-Disposition: attachment; filename=\"foo.txt\"";
print
# 打开文件
fo = open("foo.txt", "rb")

str = fo.read();
print str

# 关闭文件
fo.close()
The value of this environment variable indicates the MIME type of the information passed. Currently, the environment variable CONTENT_TYPE is generally: application/x-www-form-urlencoded, which indicates that the data comes from HTML forms.
If the information transmission method between the server and the CGI program is POST, this environment variable is 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 entered data.
COOKIE content in the client.
Provides client browser information including version number or other proprietary data.
The value of this environment variable indicates other path information immediately after the CGI program name. It often appears as a parameter to CGI programs.
If the information transfer method between the server and the CGI program is GET, the value of this environment variable is the transferred information. This information follows the CGI program name, separated by a question mark '?'.
The value of this environment variable is the IP address of the client sending the request, such as 192.168.1.67 above. This value is always present. And it is the unique identifier that the Web client needs to provide to the Web server, which can be used in CGI programs to distinguish different Web clients.
The value of this environment variable contains the host name of the client that sent the CGI request. If the query you want to query is not supported, there is no need to define this environment variable.
Provides the method by which the script is called. For scripts using the HTTP/1.0 protocol, only GET and POST are meaningful.
Full path of the CGI script
Name of the CGI script
This is the host name, alias or IP address of your WEB server.
The value of this environment variable contains the name and version number of the HTTP server that calls the CGI program. For example, the value above is Apache/2.2.14(Unix)