wsgirf-WSGI功能及参考实现

源码:Lib/wsgiref

Web服务器网关接口(Web Server Gateway Interface, WSGI),是用Python写的一个服务器软件和web应用之间的通用接口。使用通用接口,能够使同一个应用方便的被不同过的web服务器调用。

只有web服务器和软件框架作者需要知道WSGI设计的细节和极端情况。你只需要安装一个WSGI应用或者用现有框架写一个web应用,并不需要知道WSGI的全部细节。

wsgirefWSGI细则的一个参考实现,用于给web服务器和框架提供WSGI支持。它提供了处理WSGI环境变量、response头和WSGI服务器基类的功能,一个服务于WSGI应用的HTTP服务器demo,以及检测WSGI服务器和应用是否和WSGI细则(PEP 3333)是否一致的验证工具。

wsgi官网获取更多信息和相关教程。

wsgiref.util - WSGI环境工具

本模块提供了一些列用于WSGI环境的适用功能。 根据PEP 3333WSGI环境是一个包含HTTP请求变量的字典。所有接受environ参数的函数都预期接受一个兼容于WSGI的字典。详见PEP 3333

wsgiref.util.guess_scheme(environ)

通过检查环境变量中的HTTPS,返回wsgi.url_schemehttp还是https
这个函数用于,创建一个包装CGI或者FastCGI协议的网关。一般来说,提供这些协议的服务器,当使用SSL时,会提供一个值为"1", "yes"或者"on"的HTTPS变量。如果找到了,这个函数返回'https';否则,返回'http'。

wsgiref.util.request_uri(environ, include_query=True)

返回请求的URI,可选参数决定是否返回查询字符串,使用PEP 3333中的"URL Reconstruction"算法。

wsgiref.util.application_uri(environ)

request_uri方法类似,除了忽略PATH_INFO 还有QUERY_STRING变量。返回结果为发起请求的应用对象的基地址(base uri)。

wsgiref.util.shift_pathi_info(environ)

将环境变量中PAHT_INFO移动一个名字到SCRIPT_NAME,并返回。环境变量会被原地修改,如果你要保存原始值,存一个备份 。
如果PAHT_INFO中没有剩余的路径节段,返回None
一般来说,这一例行程序用于处理请求URI的每一部分,例如把路径作为一系列字典键值进行处理。这一例行程序,修改传入的环境变量,使其用于激活目标URI的WSGI应用。比如,在路径/foo上有一个WSGI应用,请求URI为/foo/bar/baz/foo处的WSGI应用调用shift_path_info(),将会得到"bar",环境变量会被更新,使其传向/foo/bar/处的WSGI应用。也就是说SCRIPT_NAME/foo变为/foo/barPATH_INFO/bar/baz变为/baz
当路径仅为"/"时,该例行程序返回空字符串,并在SCRIPT_NAME处添加末尾斜杠。尽管空路径片段一般都被忽略了。但SCRIPT_NAME一般不以斜杠结束。故意这样设计,是为了让应用在做对象遍历时,能够区分/x/x/这两个不同的路径。

# 源码
# https://github.com/python/cpython/blob/master/Lib/wsgiref/util.py#L102
if not name and not script_name.endswith('/'):
script_name += '/'

wsgiref.util.setup_testing_defaults(environ)

为了测试而更新环境变量。

这个例行程序为WSGI添加各种参数,包括HTTP_HOST, SERVER_NAME, SERVER_PORT, REQUESTS_METHOD, SCRIPT_NAME。以及PEP 3333中顶以的所有wsgi.*变量。只提供默认值,不替代现有值。

这个理性城市,是为了建立一个环境,让WSGI和应用的单元测试变得更简单。不应该应用在真实的WSGI服务器上,因为数据都是假的。

from wsgiref.util import setup_testing_defaults
from wsgiref.simple_server import make_server # A relatively simple WSGI application. It's going to print out the
# environment dictionary after being updated by setup_testing_defaults
def simple_app(environ, start_response):
# 创建虚假环境
setup_testing_defaults(environ) status = '200 OK'
headers = [('Content-type', 'text/plain; charset=utf-8')] # 发送头部
start_response(status, headers) ret = [("%s: %s\n" % (key, value)).encode("utf-8")
for key, value in environ.items()]
return ret # 这行代码我在3.6.1下运行会出错,make_server不支持上下文管理?
# 把with 语句改成普通的语句好像就没问题了。
with make_server('', 8000, simple_app) as httpd:
print("Serving on port 8000...")
httpd.serve_forever()

除了上述函数,wsgiref.util还提供了其他各种功能。

wsgiref.util.is_hop_by_hop(header_name)

根据[RFC 2616](https://tools.ietf.org/html/rfc2616.html),如果`header_name`是`"Hop-by-Hop"`返回True.

wsgiref.util.FileWrapper(filelike, blksize=8192)

一个把类文件对象转变为成迭代器的包装器。结果支持`__getitem__()`和`__iter__()`。当迭代遍历这个对象时,`blksize`参数会被重复地传给类文件对象地`read()`方法,获取产生的字节。当`read()`产生空字节时,迭代结束。
如果这个类文件对象有`close()`方法,返回的对象也有`close()`方法,当被调用时,会激活类文件对象的`close()`方法。
from io import StringIO
from wsgiref.util import FileWrapper # We're using a StringIO-buffer for as the file-like object
filelike = StringIO("This is an example file-like object"*10)
wrapper = FileWrapper(filelike, blksize=5) for chunk in wrapper:
print(chunk)

wsgi.headers WSGI response 头工具

本模块只提供一个类:Headers。使用(mapping-like interface)映射接口, 方便操作地操作WSGI地响应头。

wsgiref.headers.Headers([headers])

创建一个映射对象包装headersheaders,必须是按照PEP 3333中所规定地键值元组列表。默认值时一个空列表。】

Headers对象支持映射操作,包括__getitem()get(), __setitem()setdefault()__delitem(), 以及__contain__()。key是name,值是该name下的第一个值。

与字典不同,在你试图删除或者get一个不存在key时,Headers对象不会抛出异常。Headers的长度等于它items()的长度,

bytes()函数,返回一个格式化的字符串,用于传输HTTP响应头。每个头占一行,用冒号和控开关白分割。行为时回车+换行。结尾是一个空行

get_all(name)

返回对应name下所有的值

返回顺序为他们在最初的头中的位置,或者他们被添加进实例的顺序。可能会重复。

add_header(name, value, **_params)

添加一个头,通过关键词参数可以添加MIME参数。

在参数名里的下划线会被转换成连接符。因为连接符在python标识符中不合法,但在MIME参数中有很多连接符。

wsgiref.simple_server一个简单的WSGI HTTP服务器

本模块提供了一个简单的基于http.server的,可服务于WSGI应用的HTTP服务器。每一个服务器实例,在一个给定的主机和端口上服务于一个WSGI应用。如果你想在一个主机和端口上,服务于多个应用,你应当创建一个WSGI应用,解析PATH_INFO决定对于每个请求,应该选择哪个应用。

wsgiref.simple_server.make_server(host, port, app, server_class=WSGIServer, handle_class=WSGIRequestHandler)

在指定host和port上,创建一个新的WSGI服务器,接受来自app的连接。返回值是传入的server_class的一个实例。并会使用handler_class处理requests。app参数必须是一个符合PEP 3333定义的WSGI应用对象。

wsgirfe.simple_server.demo_app(environ, start_response)

本函数是一个小而完全的WSGI程序,返回一个包含"Hello world!"和环境变量k-v值对的文本页。用于确认WSGI服务器能够争取的处理WSGI程序。

wsgiref.simple_server.WSGIServer(server_address, RequestsHandlerClass)

创建一个WSGISever实例,server_address应当是(host, port)元组,RequestHandlerClass应当是http.server.BasedHTTPRequestHandler的子类,用于处理requests。

你不需要正式调用构造器,因为make_server()函数会帮你处理细节。

WSGIServerhttp.server.HTTPServer的子类,所以继承了其方法,如:serve_forever()handle_request()WSGIServer同时也提供了一些WSGI专有的方法。比如:

set_app(application)

设置一个可调用应用,作为接收requests的WSGI应用。

get_app()

返回目前设置的可调用应用。

一般来说,你不要调用这些额外的方法。 set_app()一般有make_server()调用,get_app()主要是为了requests handler实例而存在。

wsgiref.simple_server.WSGIRequestHandler(reqeust, client_address, server)

对于给定的request(例如,一个socket), client_address (一个(host, port)元组)server,创建一个HTTP handler。

你不需要直接创建这个类的实例,他们会由WSGIServer对象按需创建。单你可以创建一个该类的子类,作为handler_class参数,传给make_server()函数。以下为一些在子类中可能相关的需要重写的函数。

get_environ()

返回一个包含WSGI环境的字典。默认设置返回WSGIServer对象的base_environ字典属性,并加上来自HTTP request的各种头部。每次调用这个方法,都会放回一个新的字典,包含各种PEP 3333中规定的CGI环境变量。

get_stderr()

返回被用作wsgi.errors流的对象。默认设置返回sys.stderr

handle()

处理HTTP请求,默认这是使用wsgiref.hanlder类创建一个handler实例,执行真实的WSGI应用接口。

wsgirref.validate WSGI一致性检查器

当创建新的WSGI应用对象、框架、服务器和中间件时,用wsgiref.validate检查新代码是否可用是非常有用过的。本模块提供了一个能创建WSGI应用对象的函数,使WSGI服务器和WSGI应用对象能够正常通信,检查两侧协议的一致性。

注意这个应用不保证完全符合PEP 3333。这个模块不报错,不意味着肯定没错。但是,如果这个模块报错,就意味着肯定有错误。不是100%兼容。

这个模块基于Python Paste

wsgiref.validate.validator(application)`

包装application并返回一个新的WSGI应用对象,返回的应用将会把所有的请求发送给最初的应用。并且检查这个应用和启动它的服务器是否遵循WSGI规则和RFC 2616

任何检测到的不一致的结果,都会抛出一个AssertionError。但,如何处理这些异常取决于服务器。比如,wsgiref.simple_server和提前基于wsgiref.handlers的服务器,会直接输出错误信息,将回溯信息输出到sys.stderr或者其他错误流中。

这个包装器也可能用warning模块指明那些有问题的,但不完全违反PEP 3333的行为。除非用Python命令行选项或者是warning的api禁止,这些细心会被输出至sys.stderr

wsgirf.handlers 服务器/网管基类

这个模块提供了配置WSGI服务器和网关的基类。这些基类处理了大部分与一个WSGI应用之间的通信,只要给与了他们一个CGI样的环境,以及输入/输出及错误流。

wsgiref.hanlder.CGIHandler

通过sys.stdin, sys.stdout, sys.stderros.environ唤起CGI。当你想要通过一个CGI脚本运行一个WSGI程序时很有用。你可以使用CGIHandler().run(app)

这个类是BaseCGIHandler的子类,并将wsgi.run()=True, wsgi.multithread=False, wsgi.multiprocess=True,并使用sysos获取必要的CGI流和环境。(参见CGI部分和前驱知识)

wsgiref.handler.IISCGIHandler

在微软的IIS服务器上激活CGIHandler

wsgiref.handlers.BaseCGIHandler()

CGIHandler类 类似。

wsgiref.handlers.BaseHandler

一个抽象类。每个实例处理一个HTTP请求。尽管原则上你可以创建一个子类,从而能被多个请求服用。

只有一个方法能被外部调用。

run(app)

通读Python官方文档之wsgiref(未完成)的更多相关文章

  1. 通读Python官方文档之cgi

    cgi 通用网关接口 前驱知识 网关协议学习:CGI.FastCGI.WSGI 简单点说: web服务器接受请求,启动CGI:CGI接受请求,处理,返回给服务器:服务器返回给用户 cgi效率不高,每次 ...

  2. 通读Python官方文档之cgitb

    cgitb CGI脚本异常管理 源代码:Lib/cgitb.py cgitb模块为Python脚本提供了一个特殊的异常管理器.名字有点误导人,它最初设计是为了以HTML格式展示cgi脚本的大量异常信息 ...

  3. 别开心太早,Python 官方文档的翻译差远了

    近几天,很多公众号发布了 Python 官方文档的消息.然而,一个特别奇怪的现象就发生了,让人啼笑皆非. Python 文档的中文翻译工作一直是“默默无闻”,几个月前,我还吐槽过这件事<再聊聊P ...

  4. 阅读Python官方文档心得

    我会每天都阅读一些python的官方文档,并每天更新心得体会. -------------------------------------------------2016.12.08--------- ...

  5. [Python3]Python官方文档-Python Manuals

    简介 一般情况下,初学者都不愿意直接去浏览Python Manuals,即Python自带的官方文档.尤其是只有英文版的情况下,初学者更加不会去使用该官方文档了. 在这里笔者强力推荐初学者经常学会使用 ...

  6. PEP 324 subprocess 新的进程模块 -- Python官方文档译文 [原创]

    PEP 324 -- subprocess 新的进程模块(subprocess - New process module) 英文原文:https://www.python.org/dev/peps/p ...

  7. python官方文档

    Tutorialstart here Library Referencekeep this under your pillow Language Referencedescribes syntax a ...

  8. Python 官方文档解读(2):threading 模块

    使用 Python 可以编写多线程程序,注意,这并不是说程序能在多个 CPU 核上跑.如果你想这么做,可以看看关于 Python 并行计算的,比如官方 Wiki. Python 线程的主要应用场景是一 ...

  9. Python 官方文档解读(1):66 个内置函数

    Python 解释器 (CPython 3.7)内置有 66 个函数,这些函数在任何时刻都是可用的.此文是为了对这 66 个函数进行简单的梳理,便于以后可能用到它们时能想到. 1. abs(x) 返回 ...

随机推荐

  1. 【Azure API 管理】使用APIM进行XML内容读取时遇见的诡异错误 Expression evaluation failed. Object reference not set to an instance of an object.

    问题描述 使用APIM,在 Inbound 中对请求的Body内容进行解析.客户端请求所传递的Request Body为XML格式,需要从Request Body中解析出多个(Element)节点值, ...

  2. LeetCode-012-整数转罗马数字

    整数转罗马数字 题目描述:罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 ...

  3. LeetCode-055-跳跃游戏

    跳跃游戏 题目描述:给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 . 数组中的每个元素代表你在该位置可以跳跃的最大长度. 判断你是否能够到达最后一个下标. 示例说明请见LeetCod ...

  4. VIM中简化删除,光标移动和查找操作

    # 一.命令行模式下简化删除 1. 向后删除单个字符:[x] 2. 向前删除单个字符:[X] 3. 删除从光标开始到单词结尾:[dw] 删除从光标后的2个单词:[d2w] 4. 删除整个单词:[daw ...

  5. Spring Cloud Ribbon 中的 7 种负载均衡策略

    负载均衡通器常有两种实现手段,一种是服务端负载均衡器,另一种是客户端负载均衡器,而我们今天的主角 Ribbon 就属于后者--客户端负载均衡器. 服务端负载均衡器的问题是,它提供了更强的流量控制权,但 ...

  6. 还不会用springboot写接口?快看这里,手把手操作,一发入魂~

    1.springboot简介 Spring Boot 可以轻松创建可以"直接运行"的独立的.生产级的基于 Spring 的应用程序. 特征 创建独立的 Spring 应用程序 直接 ...

  7. Java案例——字符串拼接

    /*案例:将一个int数组中的元素拼接为一个字符串 分析:1.静态定义一个int数组 2.定义方法将数组元素遍历并拼接,返回类型为String 3.定义变量接受方法所拼接出来的字符串 4.输出* */ ...

  8. CentOS 7.5 安装配置tigervnc-server

    系统版本: [root@s10 ~]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) 1.安装 Gnome 包 [root@ ...

  9. 最新出炉的Java面试题(2022亲身经历)

    面试题清单 个人近来面试了不少的公司的,该挂的挂,该应付通过的应付通过,目前对面试题部分做一个系统的总结.最起码要保证被问过的问题第二次被问到的时候是可以回答并且理解的.算是一个被动输入学习的过程. ...

  10. 记-Golang获取本机IP及快速搭建局域FTP

    1 package main 2 3 import ( 4 "fmt" 5 "net" 6 "net/http" 7 "strin ...