3.1作用
不修改WSGI应用程序的情况下通过配置文件配置WSGI服务.
filter:过滤器,滤网。
pipline:管道
app:application 应用,在这个语境下我举个例子吧,lavabo(洗手盆),fish tank(鱼缸)...... 这些都是应用
composite:意为合成,或合成结构。
3.2 例子讲解ini
3.2.1
[composite:main]
use = egg:Paste#urlmap
/ = home
/blog = blog
/wiki = wiki
/cms = config:cms.ini
这是一个composite段,表示这将会根据一些条件将web请求调度到不同的应用
use = egg:Paste#urlmap表示我们奖使用Pasteegg包中urlmap来实现composite,这一个段(urlmap)
是一个通用的composite程序,根据web请求的path的前缀进行一个到应用的映射(map)
3.2.2
[app:home]
use = egg:Paste#static
document_root = %(here)s/htdocs
app是一个callable object,接受的参数(environ,start_response),这是paste系统交给application的,符合WSGI规范的参数. app需要完成的任务是响应envrion中的请求,准备好响应头和消息体,然后交给start_response处理,并返回响应消息体。
它需要一个配置文件document_root,后面的值可以是一个变量,形式为%(var)s相应的值应该在[DEFAULT]字段指明以便Paste读取。
比如:
[app:test]
use = egg:Paste#static
document_root = %(path)s/htdocs
[DEFAULT]
path = /etc/test
3.2.3
[filter-app:blog]
use = egg:Authentication#auth
next = blogapp
roles = admin
htpasswd = /home/me/users.htpasswd
[app:blogapp]
use = egg:BlogApp
database = sqlite:/home/me/blog.db
filter是一个callable object,其唯一参数是(app),这是WSGI的application对象,filter需要完成的工作是将application包装成另一个application(“过滤”),并返回这个包装后的application。
[filter-app:blog]fliter-app字段表明你希望对某个应用进行包装,需要包装的应用通过next指明(表明在下一个段中),这个字段的意思就是,在正式调用blogapp之前,我会调用egg:Authentication#auth进行一个用户的验证,随后才会调用blogapp进行处理。后面的[app:blogapp]则是定义了blogapp,并指明了需要的database参数。
3.2.4
[app:wiki]
use = call:mywiki.main:application
database = sqlite:/home/me/wiki.db
这个段和之前的app段定义类似,不同的是对于wiki这个应用,我们没有使用egg包,而是直接对mywiki.main这个模块中的application对象使用了call方法。
python,中一切皆对象,作为WSGI app的可以是一个函数,一个类,或者一个实例,使用call的话,相应的函数,类,实例中必须实现call()方法。此类app的格式用冒号分割: call(表示使用call方法):模块的完成路径名字:应用变量的完整名字
3.3使用方法
PD的主要使用就是通过读取配置文件载入WSGI应用。如下:
from paste.deploy import loadapp
wsgi_app = loadapp('config:/path/to/config.ini')
注意,这里需要指明绝对路径。
3.4定义factory函数
工厂函数的定义还是遵循之前提到的应用的协议。目前,用于工厂函数的协议有以下:
*paste.app_factory
*paste.composite_factory
*paste.filter_factory
*paste.server_factory
所有的这些都希望有一个含有__call__方法的(函数,方法,类)。
3.4.1 paste.app_factory
def app_factory(global_config, **local_conf):
return wsgi_app
global_config是一个字典,而local_conf则是关键字参数。返回一个wsgi_app(含有call方法。)
3.4.2 paste.composite_factory`
def composite_factory(loader, global_config, **local_conf):
return wsgi_app
loader是一个对象,有几个有趣的方法,get_app(name_or_uri, global_conf=None)根据name返回一个wsgi应用,get_filter()和get_server()也是一样。看一个更加复杂的例子,举例一个pipeline应用:
def pipeline_factory(loader, global_config, pipeline):
# space-separated list of filter and app names:
pipeline = pipeline.split()
filters = [loader.get_filter(n) for n in pipeline[:-1]]
app = loader.get_app(pipeline[-1])
filters.reverse() # apply in reverse order!
for filter in filters:
app = filter(app)
return app
相应的配置文件如下:
[composite:main]
use = <pipeline_factory_uri>
pipeline = egg:Paste#printdebug session myapp
[filter:session]
use = egg:Paste#session
store = memory
[app:myapp]
use = egg:MyApp
3.4.3 paste.filter_factory fliter的工厂函数和app的共产函数类似,除了它返回的是一个filter,fliter是一个仅仅把一个wsgi应用作为唯一参数的callable对象,返回一个被filter了的应用。 以下是一个例子,这个filter会检查CGI中REMOTE_USER变量是否存在,并创建一个简单的认证过滤器。
def auth_filter_factory(global_conf, req_usernames):
# space-separated list of usernames:
req_usernames = req_usernames.split()
def filter(app):
return AuthFilter(app, req_usernames)
return filter
class AuthFilter(object):
def __init__(self, app, req_usernames):
self.app = app
self.req_usernames = req_usernames
def __call__(self, environ, start_response):
if environ.get('REMOTE_USER') in self.req_usernames:
return self.app(environ, start_response)
start_response(
'403 Forbidden', [('Content-type', 'text/html')])
return ['You are forbidden to view this resource']
3.4.4 paste.filter_app_factory 和paste.filter_factory类似,接受一个wsgi应用参数,返回一个WSGI应用,所以如果改变以上代码的:
class AuthFilter(object):
def __init__(self, app, global_conf, req_usernames):
....
那么,类 AuthFilter就会作为一个filter_app_factory函数使用。
3.4.5 paste.server_factory
与以上不同的是,函数返回的是一个server,一个server也是一个callable对象,以一个WSGI应用作为参数,而后为这个应用服务。
def server_factory(global_conf, host, port):
port = int(port)
def serve(app):
s = Server(app, host=host, port=port)
s.serve_forever()
return serve
Server的实现用户可以自定义,可以参考python包wsgiref
3.4.6 paste.server_runner 与 paste.server_factory类似,不同的是参数格式。