WSGI将Web组件分成三类:
environ, start_response
): 这是一个app什么是WSGI APP:
WSGI APP是一个可调用的对象(callable object),常用的可调用的对象有三种:
1.一个函数或者类的方法:
environ, start_response
): 这是一个appclass app:
def __call__(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return []
这个可调用的对象有几点需要说明一下:
1. 接收两个参数environ和start_response:
environ是一个字典,里面储存了HTTP request的所有内容。在django里面,通常会把environ 封装成为一个request。
start_response是一个WSGI Server(http 服务器)传递过来的函数,用于将response header, status传递给Server。
start_response(status, headers), 它的作用是返回状态码 以及 头部信息, status必须是一个字符串,格式是 “状态码 + 说明”。
headers 是一个数组,按照 [(key, value), (key, value) ] 这样的格式来组织。
2.它需要返回一个可迭代的值,用于将response body传递给Server。
["hello world", "baby"]
WSGI Server
WSGI Server可以理解为就是一个实现了wsgi协议的http服务器,使用wsgi协议的方式来调用WSGI APP。
通常来说,它由两部分组成:socket
= eventlet.listen(('localhost', '8000'), backlog = 10) 定义一个wsgi http服务器
server = eventlet.spawn(event.wsgi.server, socket, app) 把service 和 app进行绑定
2. 调用app的主方法:def run(application): #服务器程序调用应用程序
environ = {}#设定参数
def start_response(status, headers): #设定状态和头部参数的回调函数
pass
result = application(environ, start_response)#调用APP
def write(data): # 这是把响应发到前端的函数
pass
def data in result: # 迭代访问,把响应发到前端
write(data)
1. 设定app所需要的参数(environ,start_response)
2. 调用app
3. 迭代访问app的返回结果(response body),并传给客户端
但实际上已经有很多已经封装好的WSGI Server供我们使用,只需简单的将APP与一些其他的参数绑定来创建一个Server,
而这个Server会将它接收到的request传递给绑定的APP。
下面是django自带的服务器:
from wsgiref.simple_server import make_server # 定义我们一个最简单的app def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b'<h1>Hello, web!</h1>'] # 创建一个服务器,IP地址为空,端口是8000,处理函数是application: httpd = make_server('', 8000, application) print('Serving HTTP on port 8000...') # 开始监听HTTP请求: httpd.serve_forever()
看, 我们已经自己编写了一个最基础的django,是不是很激动,django的本质就是这样的一种形式,是不是感觉发现了新大陆。
WSGI Middleware
middleware的概念没有appllication和server那么容易理解。
假设一个符合application标准的可调用对象,它接受可调用对象作为参数,返回一个可调用对象的对象。
那么对于server来说,它是一个符合标准的可调用对象,因此是application。
而对于application来说,它可以调用application,因此是server。
这样的可调用对象称为middleware。
middleware的概念非常接近decorator。
中间件对于app来说,它是一个service. 但是对于service来说,它确实一个app。文字说的不清晰,还是用代码来说比较好。
# 这是一个标准的application object def index(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return ['index page'] # 这是一个标准的application object def hello(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return ['hello page'] # 这是一个标准的application object def not_found(environ, start_response): start_response('404 NOT FOUND', [('Content-Type', 'text/plain')]) return ['Not Found Page'] ###上面我们定义了三个app ### 然后我们定义一个中间件 middleware, 看到没有,这个中间件的形式是跟app是一样的 def application(environ, start_response): path = environ.get('PATH_INFO', '').lstrip('/') #这句代码是获取url urls = [ # 这里定义路由 ('index', index), ('hello', hello) ] for item in urls: # 这里根据路由,执行不同的app if item[0] == path: app = item[1] return app(environ, start_response) else: return not_found(environ, start_response) # 如果找不到,则执行默认的app from wsgiref.simple_server import make_server # 创建一个服务器,IP地址为空,端口是8000,处理函数是application: httpd = make_server('', 8000, application) httpd.serve_forever()
看到没有,这个例子比上面的更加完善,利用中间件实现了路由的功能,把django最基础的功能完整的展示出来
中间件除了路由之外,还可以做很多事情,最常见的还有:
• 负载均衡,转发用户请求
• 预处理 XSL 等相关数据
• 限制请求速率,设置白名单
等等等