web server接收HTTP请求,封装环境变量,按照WSGI接口标准调用注册的WSGI Application,返回响应给客户端。
paste.deploy
openstack使用pastedeploy组件来完成WSGI服务器和应用的构建
-
section:[type: name]
-
type = composite
-
把URL请求分发给对应的app
-
-
type = app
-
app是具体的WSGI Application
-
-
type = filter-app
-
过滤并转发给app
-
-
type = filter
-
类似于filter-app,但没有next
-
-
type = pipeline
-
由filter+...+filter+app组成
-
-
# config.ini
[composite:main]
# use表明具体的分发方式
# egg:Paste#urlmap表示使用paste包中的urlmap模块
use = egg:Paste#urlmap
# key=value表示使用urlmap进行分发的参数
/ = home
/wiki = wiki
/blog = blog
/cms = config:cms.ini
[app:home]
# use指定app
# python egg
use = egg:Paste#static
[app:app2]
# config.ini
use = config:myconfig.ini#app_name
[app:app3]
# 直接调用另外一个模块中的app
use = call:myproject:application
[app:app4]
# 另外一个section
use = myotherapp
[app:app5]
# myapp.modulename
paste.app_factory = myapp.modulename:app_factory
[filter-app:blog]
# use指定过滤条件
use = egg:Authentication#auth
# next表示过滤后的app
next = blogapp
roles = admin
htpasswd = /home/me/users.htpasswd
[pipeline:main]
pipeline = filter1 egg:FilterEgg#filter2 filter3 app
[filter:filter1]
...
- app_factory
def app_factory(loader, global_config, **local_conf)
return wsgi_app
- 调用paste.deploy
from paste.deploy import loadapp
wsgi_app = loadapp('config:/path/to/config.ini')
webob
webob对WSGI请求与响应进行封装
-
webob.Request
-
对WSGI请求的environ参数进行封装
-
-
webob.Response
-
包含所有标准WSGI响应要素
-
-
webob.exc
-
封装HTTP错误代码
-
-
webob.dec.wsgify
-
封装WSGI参数和返回格式
-
-
标准WSGI格式
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return '<h1>Hello</h1>'
-
webob.dec.wsgify封装格式
@webob.dec.wsgify
def application(req):
return webob.Response('OK')
# RequestClass过滤
@webob.dec.wsgify(RequestClass=MyRequest)
WSGI
-
标准WSGI格式
def application(environ, start_response):
# HTTP请求:environ
# HTTP响应:start_response(HTTP响应码,HTTP Header, 错误信息)
start_response('200 OK', [('Content-Type', 'text/html')], exc_info=None)
# 返回Body
return '<h1>Hello</h1>'
WSGI+pastedeploy+webob
# tsroutes.ini
[composite:main]
use=egg:Paste#urlmap
/=show
[pipeline:show]
pipeline = root
[app:root]
paste.app_factory = tsroutes:Router.app_factory
# tsroutes.py
import logging
import os
import webob.dec
import webob.exc
from paste.deploy import loadapp
from wsgiref.simple_server import make_server
import routes.middleware
LOG = logging.getLogger(__name__)
class Controller(object):
@webob.dec.wsgify
def __call__(self, req):
arg_dict = req.environ['wsgiorg.routing_args'][1]
action = arg_dict.pop('action')
return webob.Response('OK')
def getMessage(self, context, user_id):
return {'Message': 'TestMessage'}
class Router(object):
def __init__(self):
self._mapper = routes.Mapper()
self._mapper.connect('/test/{user_id}',
controller=Controller(),
action='getMessage',
conditions={'method': ['GET']})
self._router = routes.middleware.RoutesMiddleware(self._dispatch, self._mapper)
@webob.dec.wsgify
def __call__(self, req):
return self._router
@staticmethod
@webob.dec.wsgify
def _dispatch(req):
match = req.environ['wsgiorg.routing_args'][1]
if not match:
return webob.exc.HTTPNotFound()
app = match['controller']
return app
@classmethod
def app_factory(cls, global_config, **local_config):
return cls()
if __name__ == '__main__':
configfile = 'tsroutes.ini'
appname = "main"
wsgi_app = loadapp("config:%s" % os.path.abspath(configfile), appname)
httpd = make_server('localhost', 8282, wsgi_app)
httpd.serve_forever()
测试:localhost:8282/test/1