Web应用的本质:
WSGI(Web Server Gateway Interface,Web 服务器网关接口)则是Python语言中所定义的Web服务器和Web应用程序之间或框架之间的通用接口标准。
WSGI就是一座桥梁,桥梁的一端称为服务端或网关端,另一端称为应用端或者框架端,WSGI的作用就是在协议之间进行转化。WSGI将Web组件分成了三类:Web 服务器(WSGI Server)、Web中间件(WSGI Middleware)与Web应用程序(WSGI Application)。
Web Server接收HTTP请求,封装一系列环境变量,按照WSGI接口标准调用注册的WSGI Application,最后将响应返回给客户端。
WSGI Server可以理解为一个符合WSGI规范的web server,接收request请求,封装一系列环境变量,按照WSGI规范调用注册的WSGI App,最后将reponse返回给客户端。
WSGI Server的基本工作流程:
#最简单的WSGI server为Python自带的wsgiref.simple_server
from wsgiref.simple_server import make_server
srv = make_server('localhost', 8080, fuc)
srv.serve_forever()
WSGI协议要求:
the application object接受两个参数且可以被多次调用
这两个参数分别为:
写法如下:
# the application object. 可以使用其他名字,
# 但是在使用mod_wsgi 时必须为 "application"
def application( environ, start_response):
# 构造响应体,以可迭代字符串形式封装
response_body = 'The request method was %s' % environ['REQUEST_METHOD']
# HTTP 响应码及消息
status = '200 OK'
# 提供给客户端的响应头.
# 封装成list of tuple pairs 的形式:
# 格式要求:[(Header name, Header value)].
response_headers = [('Content-Type', 'text/plain'),
('Content-Length', str(len(response_body)))]
# 将响应码/消息及响应头通过传入的start_reponse回调函数返回给server
start_response(status, response_headers)
# 响应体作为返回值返回
# 注意这里被封装到了list中.
return [response_body]
所谓的 WSGI中间件同时实现了API的两方,因此可以在WSGI服务和WSGI应用之间起调解作用:从WSGI服务器的角度来说,中间件扮演应用程序,而从应用程序的角度来说,中间件扮演服务器。
“中间件”组件可以执行以下功能:
写法如下 :
class Router(object):
def __init__(self):
self.mapper = Mapper()
self.mapper.connect('/test', controller=Controller(), action='test', conditions={'method': ['GET']})
self.mapper.connect('/login', controller=Controller().login, action='login', conditions={'method': ['POST']})
self.mapper.connect('/projects', controller=Controller().get_projects, action='get_projects',
conditions={'method': ['GET']})
self.mapper.connect('/services', controller=Controller().get_services, action='get_services',
conditions={'method': ['GET']})
self.router = middleware.RoutesMiddleware(self.dispatch, self.mapper) # 创建实例,调用的时候进行路由匹配,修改环境变量
@webob.dec.wsgify
def __call__(self, req):
urll = ['%s : %s' % (k, v) for k, v in sorted(req.environ.items())]
print('\n'.join(urll)) # 原始的环境变量
return self.router
@staticmethod
@webob.dec.wsgify
def dispatch(req):
urll = ['%s : %s' % (k, v) for k, v in sorted(req.environ.items())]
print('\n'.join(urll)) # 从这里可以看出来环境变量已经改变了
match = req.environ['wsgiorg.routing_args'][1]
if not match:
return webob.exc.HTTPNotFound()
app = match['controller']
return app