web.py的HTTP研究
Monday, November 26th, 2007
web.py的HTTP研究
作者: | gashero | 日期: | 2007-11-21 | 版本: | web.py-0.22 |
---|
1 简介
我想要实现使用twisted作为HTTP服务器,而web.py作为后端的动态引擎的部署方式。从而实现高性能,又易于学习的一种开发方式。
2 一个基本的例子
见web.py首页上提供的例子,如下:
import web urls=( '/(.*)','hello', ) class hello: def GET(self,name): i=web.input(times=1) if not name: name='world' for c in xrange(int(i.times)): print 'Hello,',name+'!' if __name__=="__main__": web.run(urls,globals())
可见一个web.py编写的应用包含一个url映射表,一些映射处理类,类按照请求方法命名的方法实现了对应的逻辑,最后包含一个启动服务器的语句,只要传入URL映射即可。
3 web.py所属文件简介
3.1 __init__.py
导入所有的下属模块,并且有个主函数会运行doctest测试用例。导入的模块全部分为两种,例如:
import utils from utils import *
3.2 cheetah.py
98行代码实现了cheetah的接口规范化,最终还是要导入真正的Cheetah,只是这里提供的接口比较好用。如:
def render(template,terms=None,asTemplate=False,base=None,isString=False)
3.3 db.py
自动导入DBUtils作为数据库连接池并提供web.py友好的接口。有703行代码,貌似大了一点。
3.4 debugerror.py
以Django的模板提供了调试服务器运行时的错误信息展示。316行代码。
3.5 form.py
提供了简单的表单代码生成,和貌似有数据验证功能。提供了面向对象的组织结构。215行代码的。
3.6 http.py
269行代码。实现了HTTP的一些机制,比如cookie、缓存过期、重定向等等。好像是与httpserver.py没有什么太大的耦合,但是也要小心,看到一些web.header之类的设置,这岂不是全局的?
3.7 httpserver.py
224行代码。实现了一个简单的HTTP服务器。还是基于Python自带的那个SimpleHTTPServer模块写的,所以也是单线程的。这里一共就2个函数,分别是启动不同的服务器,不过貌似都是使用wsgi方式实现的。
3.8 net.py
155行代码。IP地址验证,URL验证等等。
3.9 request.py
153行代码。好像就是请求处理的入口了。同时这里也有个 run() 函数,貌似就是启动服务器的入口。
3.10 template.py
878行代码,貌似实现了一个比较像Cheetah的模板系统吧,里面有明确的代码显示,这里面做了很多代码解析的工作,至少是有词法解析器。
3.11 utils.py
796行代码。看来就是我以前一直期望的那个具有很多超牛功能的东西,如函数的执行缓存等等。
3.12 webapi.py
369行代码。提供了一些常用功能的函数接口,如 badrequest() 、 notfound() 、 gone() 等等,这样可以加快解决过程。另外像 setcookie() 、 cookies() 、 debug() 等等也是编程所必需的。
3.13 wsgi.py
54行代码。提供了3个函数,分别是 runfcgi() 、 runscgi() 、 runwsgi() 。分别提供3种不同的发布方式。
3.14 wsgiserver/
仅内含一个 __init__.py 文件,其实是从CherryPy搞来的WSGI服务器的代码。
4 HTTP处理流程
4.1 启动服务器
启动服务器的代码:
web.run(urls,globals())
实际上是调用 web.request 模块中的 run() 函数。代码如下:
def run(inp,fvars,*middleware): autoreload=http.reloader in middleware return wsgi.runwsgi(webapi.wsgifunc(webpyfunc(inp,fvars,autoreload),*middleware))
其中首先确定是否需要动态重新装入功能,然后就是把 webpyfunc() 的调用结果,就是一个函数对象传入 webapi.wsgifunc() 函数。 webapi.wsgifunc() 函数接受两个参数,一个是 webpyfunc() 的结果,另一个是中间件列表。
4.2 webpyfunc() 生成调用请求处理器的函数
在模块 web.request 中,声明如下:
def webpyfunc(inp,fvars,autoreload=False)
参数解释:
- inp :可以是函数或一个tuple,用于URL映射
- fvars :一个dict,存储可用的变量
- autoreload :是否自动重装
完全按照例子当中执行时webpyfunc()函数的调用参数为:
webpyfunc(urls,globals(),False)
这样最终是返回的结果是:
return lambda: handle(urls,globals())
即便 autoreload=True 估计也是同样的结果,只是可以自动重新加载而已。
5 启动的HTTP服务器
经分析,默认的服务器最终启动的是 web.wsgi 模块中 runwsgi() 函数中的如下语句:
return httpserver.runsimple(func,validip(listget(sys.argv,1,'')))
这个函数实际上内部居然还包含两个类的定义,一个作为静态文件服务的,叫 StaticApp ,另外一个用作动态的,叫 WSGIWrapper 。
6 总结
真不知道wsgi为什么这么重要,以至于我接触的几个框架基本上都是用wsgi来实现底层。每每让我无法下手修改其行为。django算是走的距离核心最近的一个了,而其他的基本上还没有摸到边。
总之,还是自己写那个htmid吧,自己写的终归了解。