文章目录
  1. 1. 什么是WSGI?
    1. 1.1. 定义
    2. 1.2. 我的理解
  2. 2. WSGI规范概述
    1. 2.1. 一个简单的server例子
    2. 2.2. 一个简单的application例子
    3. 2.3. 规格的详细说明
      1. 2.3.1. (1) application
        1. 2.3.1.1. 输入参数
        2. 2.3.1.2. 输出参数
        3. 2.3.1.3. callabel object
      2. 2.3.2. (2) environ变量
      3. 2.3.3. (3) start_response(status, reponse_headers, exc_info=None)
        1. 2.3.3.1. 输入参数
        2. 2.3.3.2. 输出参数
  3. 3. 参考

什么是WSGI?

定义

Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。

注意这些关键词: python语言定义, 通用, Web服务器, Web应用程序或框架

我的理解

Web 服务基本都是基于HTTP进行请求应答, 在TCP/IP模型下, HTTP 位于应用层,使用TCP作为其传输层。
下图是 TCP服务器与TCP客户端的工作流程, 但我们现在关注的是红框里面部分—如何进行HTTP请求与应答?

对于TCP这一传输层而言,传到应用层的请求数据/接受的应答数据都是字节流,位于应用层的HTTP需要按照报文格式进行解析(或组织)后再与TCP进行传输。

HTTP报文格式

因为解析请求报文,组织应答报文工作比较烦琐, 又有点千篇一律,那就把它抽象独立出来吧,如果使用python的话,把请求报文解析为dict就好用多啦。
嗯,我们可以简单地认为这就是上述所说的Web服务器做的工作 。
这样一来,Web应用程序或框架就轻松了,累活不用干,只管逻辑,要响应时类似地把body,hander等东西扔给web 服务器打包。
WSGI就是这样的一个协议, 将位于应用层的HTTP过程进行分层次, 规定 底层的Server 与 上层的application 之间的交互的方式

实现了此“协议”的 Web application(或框架)和 Web server即可方便地结合使用,比如常用的 python 框架(如 Flask、Django、webpy等)结合Web server(uWSGI、Gunicorn 等)

WSGI规范概述

WSGI 这种“协议”并非文本格式上的商定,而是 python 对象之间的调用格式的规定。

一个简单的server例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class WSGIHandler:
def __init__(self, application):
...
self.application = application
self.handle()
...

def handle(self):
# 解析请求报文头
self.parse_request()
# 将解析好的请求报文信息,一些相关的变量参数塞到 self.environ
self.setup_environ()
# 调用符合WSGI协议的application
self.result = self.application(self.environ, self.start_response) # *

# 报文体
for data in self.result:
self.write(data)
self.close() 

def write(self, data):
if not self.headers_sent: # 确保先写报文头再写报文体
self.headers_sent = True
self._write(str(self.headers))

self._write(data)

def start_response(self, status, headers):
"""提供给application填入响应报文头内容 """
self.status = status
self.headers = self.headers_class(headers)
return self.write

一个简单的application例子

它可以被上面例子的server调用哦

1
2
3
4
def application(environ, start_response):
""" 不管请求报文内容是啥,都返回一样的东西 """
start_response('200 OK', [('Content-Type', 'text/html')]) # 报头内容
return ['Hello world!\n'] # 报文体内容

通过上面两个例子, 我们可以大概理解到 WSGI 协议大概的实现方式.(如果看一次有点模糊就再看一次)
看到这里会不会觉得,我靠,不就是函数调用嘛?

就如本文一开始所引用的定义讲的, WSGI 是一个通用, python语言定义的协议。
只要实现了此WSGI的application, 就可以不用做Server做的工作,简单地处理逻辑,毕竟Server不仅仅是解析报文,打包报文用的,它还需要做比如监听端口,包装字节流为file对象等工作。

规格的详细说明

(1) application

输入参数

接受两个参数(位置参数(positional arguments), 不一定需要像举例那样命名):

  • environ: 环境变量, 必须为Python内建的dict对象
  • start_response(status, responce_headers): callable, 用于存储报文状态码与headers, 具体要求见下文

输出参数

  • 可迭代者(iterable), 用于server调用application后产生报文主体(body)字符串

callabel object

命名无要求,但是必须是可调用的对象(callabel object), 不只是函数这种身份,比如:

  • 一个 class

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # callable class
    class Application:
    def __init__(self, environ, start_response):
    self.environ = environ
    self.start = start_response

    def __iter__(self):
    self.start('200 OK', [('Content-Type', 'text/html')])
    yield ['Hello world!\n']
  • 一个实例,它的 class 实现了__call __方法

    1
    2
    3
    4
    5
    # callable object
    class ApplicationObj:
    def __call__(self, environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return ['Hello world!\n']

(2) environ变量

详见这里, 平时使用框架开发时,会发现很多request.xxx 的东西就是出自这里

(3) start_response(status, reponse_headers, exc_info=None)

它作为一个参数,从server传给了application, application在内部调用它

输入参数

  • status: HTTP的status字符,类似200 OK, 404 Not Found, 字符串
  • responce_headers: 包含一个或多个(header_name, header_value)这个形式的元组列表。
    e.g. [(‘Content-Type’, ‘text/html’), ]
  • exc_info: 可选参数, 必须是Python的 sys.exc_info,
    如果调用start_response时HTTP头信息已经发送,就使用此参数内容抛出异常(如果提供了此参数)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def start_response(self, status, headers,exc_info=None):
    if exc_info:
    try:
    if self.headers_sent:
    # Re-raise original exception if headers sent
    raise exc_info[0], exc_info[1], exc_info[2]
    finally:
    exc_info = None # avoid dangling circular ref
    ......

输出参数

  • 返回一个write函数

参考

文章目录
  1. 1. 什么是WSGI?
    1. 1.1. 定义
    2. 1.2. 我的理解
  2. 2. WSGI规范概述
    1. 2.1. 一个简单的server例子
    2. 2.2. 一个简单的application例子
    3. 2.3. 规格的详细说明
      1. 2.3.1. (1) application
        1. 2.3.1.1. 输入参数
        2. 2.3.1.2. 输出参数
        3. 2.3.1.3. callabel object
      2. 2.3.2. (2) environ变量
      3. 2.3.3. (3) start_response(status, reponse_headers, exc_info=None)
        1. 2.3.3.1. 输入参数
        2. 2.3.3.2. 输出参数
  3. 3. 参考