Menu
- 概念
- 在windows server端需要配置apache,才能试用cgi-bin
- 在服务器安装CGI脚本
- 用户交互 (tutor3.py,tutor3.html,cgi.FieldStorage()) (未写完)
- 下载文件(getfile.py没有写)
- 上传文件(putfile.py没有写) 各平台&客户端中path里提取文件名
- HTML&URL转义
- Web状态保存(cookie)
- 运行本地网络服务器
概念
- 根据网络服务器的管理进行命名(如file.py)
- 存放在网络服务器认可的目录下(如cgi-bin/)
- 对服务器主目录需要修改权限(对所有人可读,可执行,不可写),linux下用chmod 755 filename;
- 在某些服务器上可能需要在顶部带有#!pythonpath行。
- 仅在有必要时配置sys.path,以便查找其它目录下的模块。
- 如果服务器不接受DOS格式,则使用Unix换行符惯例。Unix换行符是/n,所以二进制下传送文本文件行尾发送的是/r/n需要转换。
- 如有必要,冲洗输出缓冲,或周期性发送部分回复。
- cgi的py文件向HTML发送的内容必须都转义
- HTML转义: html.escape("<abc>") or cgi.escape("<abc>")
- HTML转义的反转:html.unescape('<abc>') # 解析后是<abc>
- url解析工具:urllib.parse.quote" or "urllib.parse.quote_plus"
- urllib.parse.quote(“upload/index.txt”, "/") # 第二个参数里的符号不转义
- url转义的反转义方法:urllib.parse.unquote_plus OR urllib.parse.unquote
- 在HTML里的超链接如果有特殊符号,需要先转义:
'<a href="http://lu.com?name=%s">aaa</a>' % urllib.parse.quote("<abc>") - 在urllib.parse中除了英文、数字、“_.-”其它都是不安全字符,都会转义。
import urllib
s = r"a@b*c/def\g... zzz"
print(urllib.parse.quote(s)) # quote 空格=="%20", "/" == "/"
print(urllib.parse.quote_plus(s)) # quote_plus空格=="+", "/" == %2F
"""
quote > a%40b%2Ac/def%5Cg...%20zzz
quote_plus > a%40b%2Ac%2Fdef%5Cg...+zzz
"""
在windows server端需要配置apache,才能试用cgi-bin
【linux环境配置方法:】
在进行CGI编程前,确保您的Web服务器支持CGI及已经配置了CGI的处理程序。
Apache 支持CGI 配置:
设置好CGI目录:
ScriptAlias /cgi-bin/ /var/www/cgi-bin/
所有的HTTP服务器执行CGI程序都保存在一个预先配置的目录。这个目录被称为CGI目录,并按照惯例,它被命名为/var/www/cgi-bin目录。
CGI文件的扩展名为.cgi,python也可以使用.py扩展名。
默认情况下,Linux服务器配置运行的cgi-bin目录中为/var/www。
如果你想指定其他运行CGI脚本的目录,可以修改httpd.conf配置文件,如下所示:
<Directory "/var/www/cgi-bin">
AllowOverride None
Options +ExecCGI
Order allow,deny
Allow from all
</Directory>
在 AddHandler 中添加 .py 后缀,这样我们就可以访问 .py 结尾的 python 脚本文件:
AddHandler cgi-script .cgi .pl .py
其实稍微有一些编程基础的小伙伴,应该很快能根据这一段得知在Windows环境的配置方法,只有路径有一些些区别,具体如下:
[Windows环境配置方法:]
1、将:ScriptAlias /cgi-bin/ "/var/www/cgi-bin" 设置为实际的目录如:ScriptAlias /cgi-bin/ "D:/Apache/cgi-bin/"
2、将:<Directory "/var/www/cgi-bin">
AllowOverride None
Options None
Order allow,deny
Allow from all
</Directory>
中的:<Directory "/var/www/cgi-bin"> 设置为实际目录,如:<Directory "D:/Apache/cgi-bin/">
# <以下是重点↓↓↓>
3、找到:AddHandler cgi-script .cgi之后,去掉前面的#号,并且在后面添加.py,如:AddHandler cgi-script .cgi .py
# <以下是重点↓↓↓>
经过以上配置之后,将编写的python脚本文件,放到Apache目录下的cgi-bin中
# <以下是重点↓↓↓>
在python文件中第一行配置python.exe路径:#!C:\Python3.5.2\python.exe
还有最重要的一点,在所有输出之前,先输出一个头
# <以下是重点↓↓↓>
print("Content-type:text/html\n")
在服务器安装CGI脚本
- 要把CGI脚本放在服务器认可的目录下
- 而且需要将它们命名为可被服务器识别的CGI脚本。本地服务器需要把CGI脚本放在cgi-bin子目录下,文件名后缀为.py。如果放在webdir目录下,和html文件放在一起的话,则需要把后缀名改为:.cgi (需要根据具体服务器来具体配置。)
- 执行CGI文件
- 文件需要配置:任何用户都能执行脚本;
- linux服务器下使用命令行:chmod 755 filename
- CGI脚本需要在顶部添加特定的“#!”行
- “#! 后面跟着的是服务器上解释器的路径”
- “#!/usr/bin/python” (不用写引号)
- 或是调用cnv程序,cnv在服务器环境变量($path)中推断python路径
- 模块搜索路径配置
- python通常默认搜索当前目录中的导入模块。
- 如果放在其他目录,需要手动添加搜索目录:sys.path.append(dirname)
用户交互
- 通过HTML的form input表格输入信息(POST模式):
<!--用户输入表单的 form模块, input表格输入,POST模式,发送给cgi-bin/mytutor.py,
mytutor模块里的cgi.FieldStorage()接收数据-->
<html>
<head>
<meta charset="utf-8">
<title>MyTutor3</title>
<head>
<body>
<h1>Input your name please!</h1>
<hr />
<form method=POST action="http://localhost/cgi-bin/mytutor.py">
<table>
<tr align="left">
<td>name:</td>
<td><input type=text name=user/></td>
</tr>
<tr align="left">
<td>age:</td>
<td><input type=text name=age></td>
</tr>
<tr align="left">
<td>pswd:</td>
<td><input type=password name=password></td>
</tr>
<tr align="canter">
<td><input type="submit"></td>
</tr>
</table>
</form>
<body>
</html>
-
通过URL name=value 传参,可传多条(GET模式):
- http://localhost/cgi-bin/mytutor.py?name=bb&age=17
- 同样在cgi-bin/mytutor.py 里的cgi.FieldStorage() 都能接收到。
- 在method=GET模式下在input表格里传参提交后会在回复页面url里显示全部name=value;
接收来自html的表单,并动态的打印出html格式在浏览器里显示:
#!/usr/bin/python
# 接收来自html的表单,并动态的打印出html格式在浏览器里显示。
"""
runs on the server, reads form input, prints HTML;
url=http://server-name/cgi-bin/tutor3.py
"""
import cgi
form = cgi.FieldStorage() # parse form data
print('Content-type: text/html') # plus blank line
html = """
<TITLE>tutor3.py</TITLE>
<H1>Greetings</H1>
<HR>
<P>%s</P>
<HR>"""
if not 'user' in form:
print(html % 'Who are you?')
else:
print(html % ('Hello, %s.' % form['user']))
HTML&URL转义
cgi.escape("<>")
"'<>'"
Web状态保存(cookie)
"""
cookie是一个类字典(键值对)对象;
"""
import http.cookies, os # server端http.cookie模块
cookstr = os.environ.get("HTTP_COOKIE") # 查找客户端环境变量的值
cookies = http.cookies.SimpleCookie(cookstr) # 用客户端环境变量的值为参数创建cookie对象;
usercook = cookies.get("user") # 获取“user”的值;
if usercook == None: # 如为空,那就是第一次登陆
cookies = http.cookies.SimpleCookie() # 创建cookie对象
cookies['user'] = 'Brian' # 创建cookie对象里的“user”键赋值;
print(cookies) # 发送cookie信息给客户端(浏览器);
greeting = '<p>His name shall be... %s</p>' % cookies['user']
else:
greeting = '<p>Welcome back, %s</p>' % usercook.value # 如是再次访问就取得信息返回;
print('Content-type: text/html\n') # plus blank line now
print(greeting) # 在浏览器打印HTML;
运行本地网络服务器
import os, sys
import http.server
webdir = r"D:\Python\PP4E-Examples-1.2\Examples\PP4E\Internet\Web"
port = 80 # 默认端口:80
os.chdir(webdir) # 一定要把webdir(要提供服务的文件夹)切换到当前工作目录
serveraddr = ("", port)
serverobj = http.server.HTTPServer(serveraddr, http.server.CGIHTTPRequestHandler) #开启服务
serverobj.serve_forever()