Python WSGI标准

WSGI(web server gateway interface,Web服务网关接口)定义了一个相对简单且标准化的设计模式,用于创建对Web请求的响应。这是大多数基于Python的Web服务器的通用框架。更多相关信息,可访问http://wsgi.readthedocs.org/en/latest/。

关于WSGI的一些背景知识,可访问https://www.python.org/dev/peps/pep-0333。

Python库中的wsgiref包包含了一个WSGI的参考实现。每个WSGI应用程序都具有相同的接口,如下所示:

def some_app(environ, start_response):
    return content

参数environ是一个字典,以单一且统一的结构包含了请求的所有参数。报头、请求方法、路径以及任何表单和上传文件的附件都会存放在这个环境中。除此之外,伴随WSGI请求处理的一些项目还提供了操作系统级的上下文。

参数start_response是一个专门用于发送状态和响应报头的函数。WSGI服务器中最终负责构建响应的部分将使用给定的start_response()函数,并构建响应文档作为返回值。

从WSGI应用程序返回的响应是字符串序列,或是会返回给用户代理的类字符串文件封装器。如果使用HTML模板工具,那么该序列可能只含有一项。在某些情况下(例如Jinja2模板)会将模板惰性渲染为文本块序列,这允许服务器交错执行模板填充和用户代理的下载。

可以对WSGI应用程序使用如下类型提示:

from typing import (
    Dict, Callable, List, Tuple, Iterator, Union, Optional
)
from mypy_extensions import DefaultArg

SR_Func =  Callable[
    [str, List[Tuple[str, str]], DefaultArg(Tuple)], None]

def static_app(
    environ: Dict,
    start_response: SR_Func
) -> Union[Iterator[bytes], List[bytes]]:

类型定义SR_Func是函数start_response的签名。请注意,该函数有一个可选参数,要求用mypy_extensions模块中的函数来定义该特征。

static_app()作为整个WSGI函数,需要使用环境参数和start_response()函数。返回的结果是字节序列,或者是基于字节的迭代器。可以扩展函数static_app()返回类型的组合,使其包含BinaryIOList[BinaryIO],但本章的任何示例都不会用到它们。

截至本书出版时,wsgiref包中尚没有完整的类型定义集合。具体而言,wsgiref.simple_server模块缺少合适的存根定义(stub definition),因此mypy会发出警告。

每个WSGI应用程序都设计成了函数的集合。可以将该集合视为嵌套的函数或一条转换链。链中的每个应用程序都会返回一个错误,或者将请求转交给另一个应用程序来确定最终结果。
通常用URL路径来确定要使用的备选应用程序,这会形成一个WSGI应用程序的树形结构,并且它们可以共享公共组件。

下面是一个非常简单的路由应用程序,它获取URL路径中的第一个元素,并以此定位另一个提供内容的WSGI应用程序。

SCRIPT_MAP = {
    "demo": demo_app,
    "static": static_app,
    "index.html": welcome_app,
}
def routing(environ, start_response):
    top_level = wsgiref.util.shift_path_info(environ)
    app = SCRIPT_MAP.get(top_level, welcome_app)
    content = app(environ, start_response)
    return content

该应用程序会使用wsgiref.util.shift_path_info()函数来调整环境。它会对environ['PATH_INFO']字典中请求路径中的各项进行头尾分割。第一个/之前的路径头部会移至环境中的SCRIPT_NAME项,PATH_INFO项则由路径的尾部内容进行更新。返回的值也会作为路径头部,其值和environ['SCRIPT_NAME']一致。在没有路径可解析的情况下,返回值为None,且不对环境进行更新。

函数routing()使用路径中的第一项来定位SCRIPT_MAP字典中的应用程序。我们使用welcome_app作为默认设置,避免请求的路径不符合映射规则,这似乎比返回HTTP的404 NOT FOUND错误要好一些。

该WSGI应用程序是一个函数,用于选取其他WSGI函数。请注意,路由函数并不返回函数,而是为所选取的WSGI应用程序提供修改过的环境。这是将任务从一个函数转移到另一个函数的典型设计模式。

框架通过正则表达式来泛化路径匹配过程。可以设想使用正则表达式序列和WSGI应用程序来配置routing()函数,而不是使用字符串到WSGI应用程序的映射。改进的routing()函数应用程序会计算每个正则表达式来寻找匹配项。在找到匹配后,在调用所请求的应用程序之前可以使用任何match.groups()函数来更新环境。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程