WSGI的全称是Web Server Gateway Interface,是Python的一套规范PEP 3333。它定义了web应用怎么跟web server交互,以及多个web 应用怎么串在一起来协力处理一个请求。
Frameworks that run on WSGI¶列举了一堆以WSGI为基础的Python Web框架。
Servers which support WSGI¶列举了支持WSGI的Web服务器。
本文是对PEP 3333的解读。
WSGI定义了三类角色
- server/gateway,简称s/g
- application/framework,简称a/f
- middleware,简称mw
Web服务主要是由request/response构成。对于request,其正常处理的流向有下面几种:
request --> s/g --> a/f
request --> s/g --> mw1 --> ... --> mwN --> a/f
反过来,对于response,可以有:
response <-- s/g <-- a/f
response <-- s/g <-- mw1 <-- ... <-- mwN <-- a/f
设置上WSGI需要a/f侧提供一个callable(函数,或者带有__call__方法的对象,或者是带有__init__的类对象)给s/g侧,来初始化服务。
这个callable代表a/f侧,并接受两个参数,一个是environ,带有环境参数;另一个是start_reponse方法,用来开始输出response。示例如下:
def simple_app(environ, start_response):
"""Simplest possible application object"""
status = '200 OK'
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
return [HELLO_WORLD]
environ中必须带有WSGI定义的强制参数(跟CGI的环境参数类似)。start_reponse的类型如下:
def start_response(status, response_headers, exc_info=None)
主要是用来传reponse内容体之前发送信息头。s/g侧所要做的就是,对于每个进来的request,调用a/f侧提供的callable。
mw要做的就是同时模拟s/g侧和a/f侧,把两侧链接起来。
从Python3开始,str表示的是Unicode字符,而不是简单的字节。HTTP协议一般是按照字节来处理消息的,要注意转换。
start_response的第一次参数是用来只是HTTP状态吗,比如200、401等等;第二个参数是信息头,包括一个项目为(header_name, header_value)的列表;第三个参数exc_info 用来在出错的时候传递信息。
start_response的返回值是另一个callable:write(body_data)
,用来写入内容体数据。但是这个callable是为了兼容老的程序,新程序不应使用。推荐的做法是通过之前a/f提供的callable来返回一个iterable,通过遍历这个iterable来获取需要发送的字节流。s/g侧不需要缓存字节流,a/f侧可以根据自己的需要来缓存字节流。
如果这个iterable有__len__()方法,那么必须每次调用都返回相同的结果,也就是需要发送的字节流的段数。如果这个iterable有close()方法,那么s/g侧必须在处理完request后调用这个close()方法。
s/g侧有可能不会完全消耗iterable的内容。另外iterable在发送第一段内容的时候,必须保证start_repsonse已被调用。
其他
- PEP 3333 – Python Web Server Gateway Interface v1.0.1
- Flask is a lightweight WSGI web application framework
(本篇完)