一个 WSGI Server 主要实现一个 web 应用的服务器端,接受从客户端传来的数据,并将其按照对应的协议(HTTP/uwsgi)解析成各种字段和对应的值。
除了接收信息以外还提供消息响应的过程。
一、调用 Application 的可调用对象

Server 端与 Application 端的交互
如图所示,WSGI Server 通过调用 WSGI Application 中定义的可调用对象将解析的协议数据传递过去,实现网关逻辑。
传到后台的数据按照规范需要有两个参数:
- environ:从协议中解析出来的字段数据以及 CGI 规范要求的数据
- start_response:一个接收两个参数的函数,可以理解是 Application 调用对象的回调,两个参数分别是 HTTP 状态码和 HTTP 消息中的响应头。
调用之后返回值即为 http 响应的 body 部分,与 start_response 传入的参数组成完整的协议返回内容。
另外图中写了可调用对象,理解下来其实就是实现了 __call__ 方法的 python 对象,这样理解下来其实也就说明了可调用对象可以是一个函数也可以是一个实现了 __call__ 方法的类,本质是一样的。
二、environ 包含的内容
1、CGI 规范要求的变量
- REQUEST_METHOD:HTTP 请求方法,GET 或者 POST;
- SCRIPT_NAME:HTTP path 中用于查找到 application 对象的部分,web 服务器通过 path 的一部分来决定由哪个 virtual host 处理;
- PATH_INFO:上一个变量中的 path 的剩余部分,即 application 要处理的部分;
- QUERY_STRING:HTTP 请求中的查询字符串,URL 中 ? 后面的内容;
- CONTENT_TYPE:HTTP 请求头中的 content-type 内容;
- CONTENT_LENGTH:HTTP 请求头中中的 content-length 内容;
- SERVER_NAME & SERVER_PORT:服务器名和端口,与之前的 SCRIPT_NAME 和 PATH_INFO 拼起来可以得到完整的 URL 路径;
- SERVER_PROTOCOL:HTTP 协议的版本,HTTP/1.0 或者 HTTP/1.1;
- HTTP_:与 HTTP 请求中的 headers 对应。
2、WSGI 协议要求的内容
- wsgi.version:表示 WSGI 版本,用一个元组存储,比如 (1, 0) 表示 1.0;
- wsgi.url_scheme:http 或者 https,https 协议包含 ssl 隧道包装;
- wsgi.input:一个文件的输入流,通过该输入流里提供的方法可以拿到 HTTP 请求的 body;
- wsgi.errors:一个输出流,当应用程序出错的时候可以将错误信息写入这里;
- wsgi.multithread:当 application 对象可能被多个线程同时调用的时候,这个值需要为 True,可能会处理一些多线程要处理的东西,比如共享内存等等;
- wsgi.multiprocess:当 application 对象可能被多个进程同时调用时,这个值需要为 True;
- wsgi.run_once:当 server 期望 application 对象在进程的生命周期内只被调用一次时,该值为 True。即这个值为 True 时,一次调用 class 之后便被锁上,无法再调用。
三、用例
下面是一个用 python 实现的简单 wsgi 服务:
# -*- coding:utf-8 -*-
import wsgiref.simple_server
def test_app(environ, start_response):
a = ""
for k, v in environ.iteritems():
a += "%s %s</br></br>" % (str(k), str(v))
start_response("200 OK", [("Content-Type", "text/html")])
print a
return str(a)
if __name__ == "__main__":
httpd = wsgiref.simple_server.make_server('', 8888, test_app)
httpd.serve_forever()
代码主要做了几件事:
1、根据 WSGI 协议要求的 application 格式定义了一个可调用对象(函数),接收 environ 和 start_response,该应用方法将会把 environ 返回;
2、主流程打开了一个 WSGI Server,监听 http 请求。
这里的 make_server 将会创建一个 WSGIServer 实例,本质上是开启了一个监听连接,接收到 http 请求后就将协议中的信息提取出来构成 environ,并调用 test_app。
使用浏览器访问后将会返回 environ 里的信息,阔以自己尝试运行类似代码看看内容。