Latest web development tutorials

Python3 CGI programming

What is CGI

CGI currently maintained by NCSA, NCSA CGI is defined as follows:

CGI (Common Gateway Interface), Common Gateway Interface, which is a program running on the server, such as: HTTP server, the client interface providing the same HTML page.


Web browsing

To better understand how CGI works, we can click on a link on a web page or URL of the process:

  • 1, use your browser to access the URL and connect to the HTTP web server.
  • 2, Web server receives the request message will be parsed URL and look accessed files on the server if there is, if there is to return the contents of the file, otherwise it returns an error message.
  • 3, the browser receives the information from the server and displays the received file or error messages.

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


CGI Chart

cgiarch


Web server configuration and support

Before you conduct CGI programming, make sure that your Web server has been configured to support CGI and CGI handler.

Apache supports CGI configuration:

Set up the CGI directory:

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

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

CGI file extension .cgi, python can also use the .py extension.

By default, Linux server configuration running cgi-bin directory is / var / www.

If you want to specify a different directory to run 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 .py suffix AddHandler, so we can access the end .py python script file:

AddHandler cgi-script .cgi .pl .py

The first CGI program

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

#!/usr/bin/python3

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! 我是来自本教程的第一CGI程序</h2>')
print ('</body>')
print ('</html>')

After you save the file modification hello.py, modify the file permissions to 755:

chmod 755 hello.py 

The above program is displayed in the browser to access the results are as follows:

The hello.py this script is a simple Python script, the script of the first output line "Content-type: text / html" to send to the browser type and tell the browser to display the content as "text / html".

Print output with a blank line is used to tell the server end of the header information.


HTTP header

hello.py file contents in: part of the HTTP header is "Content-type text / html", it will be sent to the browser content type tells the browser files.

HTTP header format is as follows:

HTTP 字段名: 字段内容

E.g:

Content-type: text/html

The following table describes the information in the HTTP header CGI programs are often used:

head description
Content-type: MIME entity corresponding to the information request. For example: Content-type: text / html
Expires: Date Response date and time expired
Location: URL To redirect the recipient to a non-location URL request to complete the request or identification of new resources
Last-modified: Date Requested resource was last modified
Content-length: N Content-Length request
Set-Cookie: String Http Cookie settings

CGI Environment Variables

All CGI programs have received the following environment variables, which played an important role in the CGI program:

variable name description
CONTENT_TYPE This value indicates that the environment variable to the MIME type of information transfer. At present, the environment variables are generally CONTENT_TYPE: application / x-www-form-urlencoded, he said that the data from the HTML form.
CONTENT_LENGTH If the transfer mode server and CGI program information is POST, even if the environment variable STDIN input the number of bytes that can be read valid data from the standard. This environment variable when reading the input data must be used.
HTTP_COOKIE COOKIE content within the client.
HTTP_USER_AGENT Providing information includes the version number of the client browser or other proprietary data.
PATH_INFO The value of this environment variable indicates the name of the CGI program immediately after the additional path information. It often appears as an argument CGI program.
QUERY_STRING If the transfer mode server and CGI program information is information GET, the value of this environment variable even if passed. This information is followed by the name of the CGI program, both in the middle with a question mark '?' Separator.
REMOTE_ADDR The value of this environment variable is the IP address of the client sends a request, for example, the above 192.168.1.67. This value is always present. And it is the need to provide the Web client to the Web server's unique identifier can be used in CGI programs to distinguish between different Web client.
REMOTE_HOST The value of this environment variable contains the host name of the requesting client of CGI. If it does not you want to check, you do not need to define this environment variable.
REQUEST_METHOD It provides a method called script. For HTTP / 1.0 protocol script only GET and POST meaningful.
SCRIPT_FILENAME The full path to CGI scripts
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 call CGI program name and version number of the HTTP server. For example, the above value of Apache / 2.2.14 (Unix)

Here is a simple CGI script output CGI environment variables:

#!/usr/bin/python3

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 test.py, and modify the file permissions to 755, execution results are as follows:


GET and POST methods

Browser client to the server to deliver information in two ways, both of which method is GET and POST methods.

Use the GET method of transferring data

GET method to send the encoded user information to the server, the data information is contained in the URL of the page request to number divided as follows "?":

http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2
GET requests about some of the other comments:
  • GET request can be cached
  • GET request remains in the browser history
  • GET requests can be bookmarked
  • GET requests should not be used when dealing with sensitive data
  • GET requests have length restrictions
  • GET requests should only be used to retrieve data

Examples of simple url: GET method

The following is a simple URL, using GET method to send two parameters to hello_get.py program:

/cgi-bin/test.py?name=本教程&url=http://www.w3big.com

A code hello_get.py file:

#!/usr/bin/python3

# 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>本教程 CGI 测试实例</title>")
print ("</head>")
print ("<body>")
print ("<h2>%s官网:%s</h2>" % (site_name, site_url))
print ("</body>")
print ("</html>")

After you save the file modification hello_get.py, modify the file permissions to 755:

chmod 755 hello_get.py 

Browser requests output:

Examples of simple form: GET method

The following is a two send data to the server using the GET method via an HTML form, submitted the same server script hello_get.py file, hello_get.html code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>本教程(w3big.com)</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 store a script file, we will be under the test directory, modify the file permissions hello_get.html stored as 755:

chmod 755 hello_get.html

Gif presentation is as follows:

Use the POST method to pass data

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

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

#!/usr/bin/python3

# 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>本教程 CGI 测试实例</title>")
print ("</head>")
print ("<body>")
print ("<h2>%s官网:%s</h2>" % (site_name, site_url))
print ("</body>")
print ("</html>")

Following is a form to submit data to the server script hello_get.py by POST method (method = "post"):

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>本教程(w3big.com)</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>
</form>

Gif presentation is as follows:

CGI program to pass data through the checkbox

checkbox used to submit one or more option data, HTML code is as follows:

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

A code checkbox.py file:

#!/usr/bin/python3

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

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

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

if form.getvalue('w3big'):
   w3big_flag = "是"
else:
   w3big_flag = "否"

print ("Content-type:text/html")
print ()
print ("<html>")
print ("<head>")
print ("<meta charset=\"utf-8\">")
print ("<title>本教程 CGI 测试实例</title>")
print ("</head>")
print ("<body>")
print ("<h2> 本教程是否选择了 : %s</h2>" % w3big_flag)
print ("<h2> Google 是否选择了 : %s</h2>" % google_flag)
print ("</body>")
print ("</html>")

Modify checkbox.py permissions:

chmod 755 checkbox.py

Browser Access Gif presentation charts:

Radio data transfer via CGI program

Radio only transfer data to a server, HTML code is as follows:

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

radiobutton.py script code is as follows:

#!/usr/bin/python3

# 引入 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>本教程 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 Gif presentation charts:

Textarea transfer data via CGI program

Textarea pass multiple rows of data to the server, HTML code is as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>本教程(w3big.com)</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/python3

# 引入 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>本教程 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 presentation charts:

Drop-down pass data through the CGI program.

HTML drop-down box code as follows:

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

dropdown.py script code as follows:

#!/usr/bin/python3

# 引入 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>本教程 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 Access Gif presentation charts:


CGI is used Cookie

Http protocol in a big drawback is wrong to judge a user's identity, which give programmers a great deal of inconvenience, but appears cookie functionality made up for this deficiency.

cookie that is accessing the script while the customer through the customer's browser on the client hard disk to write data records, retrieve data when a customer visits the next script, so as to achieve the function of determining the identity, cookie commonly used in verifying identity.

cookie syntax

Http cookie is sent through the http header to achieve, he had to transfer files, header set-cookie syntax is as follows:

Set-cookie:name=name;expires=date;path=path;domain=domain;secure 
  • name = name: to set the value of the cookie (name can not be used ";" and "," number), when there are multiple name values ";" to separate, for example: name1 = name1; name2 = name2 ; name3 = name3.
  • expires = date: cookie expiration date in the format: expires = "Wdy, DD- Mon-YYYY HH: MM: SS"
  • path = path: the path set cookie support, if the path is a path, the cookie for all files and subdirectories of the directory entry into force, for example: path = "/ cgi-bin /", if the path is a file, cookie It refers to the entry into force of this file, for example: path = "/ cgi-bin / cookie.cgi".
  • domain = domain: the domain name of the cookie is valid, for example: domain = "www.w3big.com"
  • secure: If this flag is given, that the cookie can only be transmitted through SSL protocol https server.
  • cookie is received by setting environment variables HTTP_COOKIE achieved, CGI programs can obtain information by retrieving the cookie variable.

Cookie settings

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

#!/usr/bin/python3
# 
print ('Content-Type: text/html')
print ('Set-Cookie: name="本教程";expires=Wed, 28 Aug 2016 18:30:00 GMT')
print ()
print ("""
<html>
  <head>
    <meta charset="utf-8">
    <title>本教程(w3big.com)</title>
  </head>
    <body>
        <h1>Cookie set OK!</h1>
    </body>
</html>
""")

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

chmod 755 cookie_set.py

The above examples use the Set-Cookie header to set the Cookie information, options set Cookie other attributes, such as the expiration time Expires, domain Domain, Path Path. This information is provided: Before "Content-type text / html".


Retrieving Cookie Information

Cookie information retrieval page is very simple, in the CGI environment variables HTTP_COOKIE, the storage format is as follows Cookie information is stored:

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

Here is a simple CGI program to retrieve cookie information:

#!/usr/bin/python3

# 导入模块
import os
import Cookie

print ("Content-type: text/html")
print ()

print ("""
<html>
<head>
<meta charset="utf-8">
<title>本教程(w3big.com)</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 code above to cookie_get.py, and modify cookie_get.py permissions:

chmod 755 cookie_get.py

More color Gif cookie settings are as follows:

Examples of file uploads

HTML settings file to upload need to set the enctype attribute to multipart / form-data, code as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>本教程(w3big.com)</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/python3

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>本教程(w3big.com)</title>
</head>
<body>
   <p>%s</p>
</body>
</html>
""" % (message,))

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

chmod 755 save_file.py

More color Gif cookie settings are as follows:

If you are using Unix / Linux, you must replace the file separator at window only need to use open () statement can be:

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

File Download dialog box

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

Download the file by setting the HTTP header information to implement the function code is as follows:

#!/usr/bin/python3

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

str = fo.read();
print (str)

# 关闭文件
fo.close()