python Web 之基石 - - CGI 编程 (基于python3)

一 、CGI 编程之前缀篇

1、CGI 入门简介

CGI:是通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口。通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。组成CGI通信系统的是两部分:一部分是html页面,就是在用户端浏览器上显示的页面。另一部分则是运行在服务器上的CGI程序。

首先,我们应该明确的是CGI只是一种接口模式,是现代的web开发的基础,这里的CGI程序可以是Python脚本,PERL脚本,SHELL脚本,C或者C++程序等。本篇文章会涉及到一些web后端处理程序(python3编写),一小部分前端H5部分,以及apache2 服务器的初级使用教程(涵盖基础配置,设置等)。

这里附上一张运行示意图:(如下)

原理图

2、Apache2 的安装以及配置(运行环境搭建)

注释:这里笔者用的是Ubuntu 16.04 + python3.5 +mysql数据库 运行环境

  • sudo apt-get install apache2
  • 检查是否成功
    • systemctl status apache2
    • 第二步,打开你的浏览器,在导航栏里输入 localhost 回车
    • 此时,出现Apache2 在Ubuntu 的导航网页,说明初步成功
  • 接下来,开始配置Apache2 的 CGI 编程环境,这里先讲述一下,默认安装后,有这几个目录需要注意一下。/etc/apache2 , /var/www/html ,/var/log/apache2/error(日志文件,经常用)

    • 为了我们方便编程,于是将编辑目录放在自己的用户目录,不用每次访问编写时,都需要sudo提高权限
    • apache2在/etc/apache2和/etc/apache2/sites-available两个文件夹下面分别有apache2.conf和000-default.conf两个配置文件需要改。然后,在自己的用户目录 mkdir -p www/html 和 mkdir -p www/cgi-bin 以后,html 和CGI都放置在相应得目录里面即可。

      • 编辑/etc/apache2/apache2.conf这个文件,找到<DDirectory /var/www/>这个选项,把其中的/var/www/修改为/home/chen/www注意这里的chen是笔者的用户目录,改成自己的用户目录。(原来的配置删掉或注释)

        -这里是我的一些配置

<Directory /home/chen/www/>
    Options Indexes FollowSymLinks ExecCGI
    AllowOverride All 
    Order allow,deny
    Allow from all
    AddHandler cgi-script .cgi .pl .py 
    Require all granted
    </Directory>
    少的东西自行添加
     - 编辑/etc/apache2/sites-available/000-default.conf这个文件,找到"DocumentRoot /var/www/html" 这个选项,把其中的/var/www/html修改为`/home/chen/www/html`。
     - 使用命令`sudo /etc/init.d/apache2 restart`来重启**apache**服务。
     - 在浏览器地址栏输入服务器地址,此时显示的是自定义目录下的文件(/home/chen/www/html ) 。
     - 接下来配置CGI 相关
         -  在`/etc/apache2/apache2.conf`文件中最后添加如下一行:
         - `ScriptAlias /cgi-bin/ /home/chen/www/cgi-bin/`
         - 这一行的意思是告诉Apache:任何以/cgi-bin/开头的资源都将映射到/home/chen/www/cgi-bin/目录中,且视之为CGI程序。
         -  导入cgid包   ,接着在刚才文件最后加入 `LoadModule cgid_module /usr/lib/apache2/modules/mod_cgid.so`
 - 接下来就可以测试一下,是否配置好了
 - 在自定义的/cgi-bin/文件夹中创建一个测试文件simple1.py 
#!/usr/bin/python
print 'Content-Type: text/html'
print ''
print '<html>'
print '<h2>CGI Script Output</h2>'
print '<p>This page was generated by a Python CGI script.</p>'
print '</html>
 - 用命令chmod 755 simple1.py赋予文件执行权限浏览器地址栏中输入地址:`http://localhost/cgi-bin/simple1.py`
 - 如果有如下输出,这说明安装成功了

 ![first CGI ](https://img-blog.csdn.net/20171201170430640?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc21pbGVqaWFzbWlsZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

注:安装过程如果出现错误,实在不能解决,可重新安装Apache 恢复默认,这里附上,完全卸载的方法 Apache 完全卸载

二 、开始 CGI programming 之旅

注:以下的 CGI 程序运行时,都需要使用chmod 755 EXE 提高执行权限,才可以运行,下面就不在重复讲述了

1 、HTTP相关知识讲述 - - - first

  • HTTP头部的格式如下:
HTTP 字段名: 字段内容

例如:
Content-type: text/html 即为HTTP头部的一部分,它告诉浏览器文件的内容类型是html格式。
- CGI程序HTTP头部常用信息:

这里写图片描述

  • CGI 的相关环境变量 — 通过环境变量进行相互通信

    这里写图片描述
    这里写图片描述

  • GET和POST方法
    浏览器客户端通过两种方法向服务器传递信息,这两种方法就是 GET 方法和 POST 方法。将在后面结合代码讲解。

2 、demo 随后 - - - - second

  1. 输出Apache 相关的运行信息 ,建立 environment.py 文件
#!/usr/bin/python3

import codecs,sys
import os
sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)

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>")

前三句代码主要是为了防止中文乱码,chmod 755 ,在导航栏输入localhost/cgi-bin/environment.py 即可运行

2、- 使用GET方法传输数据
GET方法发送编码后的用户信息到服务端,数据信息包含在请求页面的URL上,以”?”号分割, 如下所示:
http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2 有关 GET 请求的其他一些注释:
- GET 请求可被缓存
- GET 请求可被收藏为书签
- GET 请求不应在处理敏感数据时使用
- GET请求有长度限制 GET 请求只应当用于取回数据

  • 简单的url实例:GET方法
    以下是一个简单的URL,使用GET方法向hello_get.py程序发送两个参数:
    /cgi-bin/test.py?name=chen&url=http://Mr.chen’s site
#!/usr/bin/python3                                               

import codecs ,sys 
sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)

# 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>The site of Mr.chen </title>")
print ("</head>")
print ("<meta charset=\"utf-8\">")
print ("<title> Mr.chen </title>")
print ("</head>")
print ("<body>")
print ("<h2>%s官网:%s</h2>" % (site_name, site_url))
print ("</body>")
print ("</html>")      

浏览器输入localhost/cgi-bin/test.py?name=chen&url=http://Mr.chen's site 访问

3 、简单的表单实例:GET方法,以下是一个通过HTML的表单使用GET方法向服务器发送两个数据,提交的服务器脚本同样是hello_get.py文件,H5代码如下:

<!DOCTYPE html>                                                  
<html>
    <head>
        <meta charset="utf-8">
        <title> Mr.chen site</title>
    </head>
    <body>
        <form action="/cgi-bin/hello-get.py" method="get">
            this  is  www.futhureme.cn.  Welcome   Mr.chen   arrived ! ha ha  <br />  
            站点名称: <input type="text" name="name">  <br />

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

浏览器输入localhost/hello-get.html 访问

4 、使用POST方法传递数据,使用POST方法向服务器传递数据是更安全可靠的,像一些敏感信息如用户密码等需要使用POST传输数据。

以下同样是hello_get.py ,它也可以处理浏览器提交的POST表单数据:

#!/usr/bin/python3                                               

import codecs ,sys 
sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)

# 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> Mr.chen </title>")
print ("</head>")
print ("<body>")
print ("<h2>%s官网:%s</h2>" % (site_name, site_url))
print ("</body>")
print ("</html>")  

表单通过POST方法(method=”post”)向服务器脚本 hello_get.py 提交数据,将上述的 html 中的 改为 method=”post” 即可。

5 、通过CGI程序传递checkbox数据
checkbox用于提交一个或者多个选项数据,HTML代码如下

<!DOCTYPE>
<html>
    <head>
        <meta charset="utf-8">
        <title> Mr.chen(www.Mr_chen.cn) </title>
    </head>
    <body>
        <form action = "/cgi-bin/checkbox.py" method = "POST" target = "_blank">
            <input type = "checkbox" name = "http://blog.csdn.net/smilejiasmile" value = "on" /> The site of Mr.smile
            <input type = "checkbox" name = "google" value = "on" /> Google     <br /> <br />
            <input type = "submit" value = "选择站点" />
        </form>
    </body>
</html>

checkbox.py 文件的代码为:

#!/usr/bin/python3 

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

# 创建 FieldStorage
form = cgi.FieldStorage()

# 接收字段数据
if form.getvalue('google'):
    google_flag = 'yes'
else:
    google_flag = 'No'

if form.getvalue('http://blog.csdn.net/smilejiasmile'):
    smile_flag = 'yes'
else:
    smile_flag = 'No'

print ('Content-type:text/html')
print ()
print ('<html>')
print ('<head>')
print ('<meta charset = \'utf-8\'>')
print ('<title> Mr.chen\'s site </title>')
print ('</head>')
print ('<body>')
print ('<h2> Mr.chen\'s site is choised : %s </h2>'%smile_flag)
print ('<h2> Google is choised : %s </h2>' %google_flag)
print ('</body>')
print ('</html>')

改权限 755 ,浏览器输入`localhost/checkbox.html

6 、通过CGI程序传递 Textarea 数据
Textarea 向服务器传递多行数据,HTML代码如下:

<!DOCTYPE>
<html>
    <head>
        <meta charset = "utf-8">
        <title> Mr.chen's site </title>
    </head>
    <body>
        <form action = "/cgi-bin/textarea.py" method = "post"target ="_parent">
            please enter you content - - - - <br />
<textarea name = "textcontent" cols = "80" rows = "6">
</textarea>     <br /><br />
            <input type = "submit" value = "click after suring" />
        </form>
    </body>
</html>

textarea.py 脚本代码

#!/usr/bin/python3 

import codecs ,sys
sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)

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

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

# 接收字段数据
if form.getvalue('textcontent'):
    text_content = form.getvalue('textcontent')
else:
    text_content = 'nothing'

print ('Content-type:text/html')
print ()
print ('<html>')
print ('<head>')
print ("<meta charset = \'utf-8\'>")
print ('<title> The site of Mr.chen </title>')
print ('</head>')
print ('<body>')
print ('<h2> you input content is :<pre>    %s </h2>'% text_content)
print ('</body>')
print ('</html>')

7 、通过CGI程序传递下拉数据框。
HTML 下拉框代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset = "utf-8">
        <title> The site of Mr.chen </title>
    </head>
    <body>
        <form action = "/cgi-bin/dropdown.py"  method = "post" target = "_parent">
            <select name = "dropdown">
                <option value = "Mr.chen's site" selected> chen </option>
                <option value = "Google"> Google </option>
            </select>
        <input type = "submit" value = "click after suring" />
        </form>
    </body>
</html>

dropdown.py 脚本代码:

#!/usr/bin/python3 

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

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

# 接受字段数据
if form.getvalue('dropdown'):
    dropdown_value = form.getvalue('dropdown')
else:
    dropdown_value = 'Nothing'

print ("Content-type:text/html")
print ()
print ('<html>')
print ('<meta charset = \'utf-8\'>')
print ('<title> The site of Mr.chen </title>')
print ('</head>')
print ('<body>')
print ('<h2> your choise is : %s </h2>' % dropdown_value)
print ('</body>')
print ('</html>')

8 、CGI中使用Cookie , cookie 就是在客户访问脚本的同时,通过客户的浏览器,在客户硬盘上写入纪录数据 ,当下次客户访问脚本时取回数据信息,从而达到身份判别的功能,cookie 常用在身份校验中。

  • cookie的语法
    http cookie的发送是通过http头部来实现的,他早于文件的传递,头部set-cookie的语法如下:
Set-cookie:name=name;expires=date;path=path;domain=domain;secure 
  • name=name: 需要设置cookie的值(name不能使用”;”和”,”号),有多个name值时用 “;” 分隔,例如:name1=name1;name2=name2;name3=name3。
  • expires=date: cookie的有效期限,格式: expires=”Wdy,DD-Mon-YYYY HH:MM:SS”
  • path=path: 设置cookie支持的路径,如果path是一个路径,则cookie对这个目录下的所有文件及子目录生效,例如: path=”/cgi-bin/”,如果path是一个文件,则cookie指对这个文件生效,例如:path=”/cgi-bin/cookie.cgi”。
  • domain=domain: 对cookie生效的域名,例如:domain=”www.runoob.com”
    secure: 如果给出此标志,表示cookie只能通过SSL协议的https服务器来传递。
    -cookie的接收是通过设置环境变量HTTP_COOKIE来实现的,CGI程序可以通过检索该变量获取cookie信息。

9 、Cookie设置
Cookie的设置非常简单,cookie会在http头部单独发送。以下实例在cookie中设置了name 和 expires:

注意这儿的时间设置,不要让cookie过时了就行。

#!/usr/bin/python3 

print ('Content-type:text/html')
print ("Set-Cookie: name = 'Mr.chen';expires = Wed,1 Dec 2017 18:30:00 GMT")
print ()
print ("""
<html>
    <head>
        <meta charset = "utf-8">
        <title> The site of Mr.chen </title>
    </head>
        <body>
            <h1> Cookie set OK ! </h1>
        </body>
</html>
""")

修改权限 755 ,浏览器运行即可完成设置cookie

以上实例使用了 Set-Cookie 头信息来设置Cookie信息,可选项中设置了Cookie的其他属性,如过期时间Expires,域名Domain,路径Path。这些信息设置在 “Content-type:text/html”之前。

10 、检索Cookie信息
Cookie信息检索页非常简单,Cookie信息存储在CGI的环境变量HTTP_COOKIE中,存储格式如下:
key1=value1;key2=value2;key3=value3….

demo 如下:

#!/usr/bin/python3 

import codecs ,sys
sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)

# 导入模块
import os
from http import cookies

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

print ("""
<html>
    <head>
        <meta charset = "utf-8">
        <title> The sie of chen </title>
    </head>
    <body>
        <h1> reading cookie 信息 </h1>
""")
if 'HTTP_COOKIE' in os.environ:
    cookie_string = os.environ.get('HTTP_COOKIE')
    c = cookies.SimpleCookie()
    c.load(cookie_string)

    try:        # 捕捉异常
        data = c['name'].value
        print ("<h2> cookie data: "+ data + "</h2> <br>")
    except KeyError:
        print ("cookie 没有设置或者已经过时 <br>")


print ("""
    </body>
    </html>
    """)

修改权限 755 ,浏览器运行即可完成获取 。

11 、文件上传实例
HTML设置上传文件的表单需要设置 enctype 属性为 multipart/form-data,代码如下所示:

<!DOCTYPE>
<html>
    <head>
        <meta charset = "utf-8">
        <title> The site of Mr.chen </title>
    </head>
    <body>
        <meta charset = "utf-8">
        <form enctype = "multipart/form-data"
            action = "/cgi-bin/save_file.py" method = "post">
            <p> 选中文件:
            <imput type = "file" name = "filename" id = "file" class = "inputfile"/>
            <imput type = "file" name = "filename" id = "file" class = "inputfile"/>  </p>
            <p><input type = "submit" value = "upload" /></p>
        </form>
    </body>
</html>

save_file.py脚本文件代码:

#!/usr/bin/python3 

import cgi,os
import cgitb;
cgitb.enable()

form = cgi.FieldStorage()

# 获取文件名 
fileitem = form['filename']

# 检测文件是否上传
if fileitem.filename:
    # 设置文件路径
    fn = os.path.basename(filename)
    open('/tmp/'+fn,'wb').write(fileitem.file.read())

    message = '文件 "' + fn + '" upload success'

else:
    message = 'no file upload'
print("""\
        Content-Type:text/html\n
        <html>
        <head>
        <meta charset= 'utf-8'>
        <title> The site of Mr.chen </title>
        </head>
        <body>
            <p>%s </p>
        </body>
        </html>
        """%(message,))

修改权限 755 ,浏览器运行即可。

12 、文件下载对话框
我们先在当前目录下创建 foo.txt 文件,用于程序的下载。
文件下载通过设置HTTP头信息来实现,功能代码如下:

#!/usr/bin/python3

# HTTP 头部
print ("Content-Disposition:attachment;filename = \"foo.txt\"")
print ()

#打开文件
fo = open("foo.txt","rb")

str = fo.read();

print(str)

# 关闭文件
fo.close()

注: 本文参考,自己的学习笔记,以及一些网站,如,runoob 等,整合而成。
—- Mr.chen

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

smilejiasmile

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值