On this page
20.4. wsgiref — WSGIUtil 和参考实现
2.5 版的新Function。
Web 服务器网关接口(WSGI)是 Web 服务器软件和用 Python 编写的 Web 应用程序之间的标准接口。具有标准的界面可以轻松地将支持 WSGI 的应用程序与许多不同的 Web 服务器一起使用。
只有 Web 服务器和编程框架的作者才需要了解 WSGI 设计的每个细节和特殊情况。您无需仅安装 WSGI 应用程序或使用现有框架编写 Web 应用程序就了解 WSGI 的每个细节。
wsgiref是 WSGI 规范的参考实现,可用于将 WSGI 支持添加到 Web 服务器或框架。它提供用于处理 WSGI 环境变量和响应 Headers 的 Util,用于实现 WSGI 服务器的 Base Class,为 WSGI 应用程序提供服务的演示 HTTP 服务器以及用于检查 WSGI 服务器和应用程序是否符合 WSGI 规范( PEP 333)的验证工具。
有关 WSGI 的更多信息以及教程和其他资源的链接,请参见https://wsgi.readthedocs.org/。
20.4.1. wsgiref.util – WSGI 环境 Util
该模块提供了用于 WSGI 环境的各种 Util Function。 WSGI 环境是包含 PEP 333中描述的 HTTP 请求变量的字典。所有带有* environ *参数的函数都希望提供符合 WSGI 的字典;请参阅 PEP 333了解详细说明。
wsgiref.util.
guess_scheme
(环境)- pass检查* environ *词典中的
HTTPS
环境变量,返回关于wsgi.url_scheme
是“ http”还是“ https”的猜测。返回值是一个字符串。
- pass检查* environ *词典中的
当创建包装 CGI 或类似 CGI 的协议(如 FastCGI)的网关时,此Function很有用。通常,提供此类协议的服务器在pass SSL 接收到请求时将包括一个HTTPS
变量,其值为“ 1”,“是”或“开”。因此,如果找到该值,此函数将返回“ https”,否则返回“ http”。
wsgiref.util.
request_uri
(* environ , include_query = 1 *)- 使用 PEP 333的“ URL 重构”部分中找到的算法,返回完整的请求 URI(可选地包括查询字符串)。如果* include_query *为 false,则查询字符串不包含在结果 URI 中。
wsgiref.util.
application_uri
(环境)- 与request_uri()相似,但忽略
PATH_INFO
和QUERY_STRING
变量。结果是请求所寻址的应用程序对象的基本 URI。
- 与request_uri()相似,但忽略
wsgiref.util.
shift_path_info
(环境)- 将单个名称从
PATH_INFO
转换为SCRIPT_NAME
,然后返回该名称。 * environ 字典是就地修改的*;如果您需要保持原始的PATH_INFO
或SCRIPT_NAME
完整,请使用副本。
- 将单个名称从
如果PATH_INFO
中没有剩余的路径段,则返回None
。
通常,此例程用于处理请求 URI 路径的每个部分,例如,将该路径视为一系列字典键。该例程修改了传入的环境,使其适合于调用位于目标 URI 处的另一个 WSGI 应用程序。例如,如果在/foo
处有一个 WSGI 应用程序,并且请求 URI 路径是/foo/bar/baz
,而在/foo
处的 WSGI 应用程序则调用shift_path_info(),它将收到字符串“ bar”,并且环境将被更新以适合传递给/foo/bar
处的 WSGI 应用程序。也就是说,SCRIPT_NAME
从/foo
变为/foo/bar
,并且PATH_INFO
从/bar/baz
变为/baz
。
当PATH_INFO
只是一个“ /”时,此例程将返回一个空字符串并将尾部斜杠附加到SCRIPT_NAME
,即使通常会忽略空路径段,并且SCRIPT_NAME
通常不会以斜杠结尾。这是有意的行为,以确保应用程序在使用此例程进行对象遍历时可以区分以/x
结尾的 URI 与以/x/
结尾的 URI 之间的区别。
wsgiref.util.
setup_testing_defaults
(环境)- 为了测试目的,使用简单的默认值更新* environ *。
此例程添加了 WSGI 所需的各种参数,包括HTTP_HOST
,SERVER_NAME
,SERVER_PORT
,REQUEST_METHOD
,SCRIPT_NAME
,PATH_INFO
以及所有 PEP 333定义的wsgi.*
变量。它仅提供默认值,并且不替换这些变量的任何现有设置。
该例程旨在使 WSGI 服务器和应用程序的单元测试更容易设置虚拟环境。实际的 WSGI 服务器或应用程序都不应使用它,因为数据是伪造的!
Example usage:
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')]
start_response(status, headers)
ret = ["%s: %s\n" % (key, value)
for key, value in environ.iteritems()]
return ret
httpd = make_server('', 8000, simple_app)
print "Serving on port 8000..."
httpd.serve_forever()
除了上面的环境Function之外,wsgiref.util模块还提供了以下各种 Util:
wsgiref.util.
is_hop_by_hop
(* header_name *)- 如果'header_name'是 HTTP_1.1 RFC 2616定义的“逐跳”Headers,则返回 true。
-
- class *
wsgiref.util.
FileWrapper
(* filelike , blksize = 8192 *)
- class *
如果* filelike 具有close()
方法,则返回的对象也将具有close()
方法,并且在调用时将调用 filelike *对象的close()
方法。
Example usage:
from StringIO 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
20.4.2. wsgiref.headers – WSGI 响应头工具
该模块提供了一个单一类Headers,以便使用类似于 Map 的接口方便地操作 WSGI 响应 Headers。
-
- class *
wsgiref.headers.
Headers
(* headers *)
- class *
Headers个对象支持典型的 Map 操作,包括getitem(),get()
,setitem(),setdefault()
,delitem(),contains()和has_key()
。对于每种方法,键都是 Headers 名称(不区分大小写),并且值是与该 Headers 名称关联的第一个值。设置标题会删除该标题的所有现有值,然后在包装的标题列表的末尾添加一个新值。通常保留标题的现有 Sequences,将新的标题添加到包装列表的末尾。
与字典不同,当您try获取或删除包装的标题列表中没有的键时,Headers个对象不会引发错误。获取不存在的 Headers 只会返回None
,而删除不存在的 Headers 则无济于事。
Headers个对象还支持keys()
,values()
和items()
方法。如果存在多值 Headers,则keys()
和items()
返回的列表可以多次包含同一键。 Headers对象的len()
与其items()
的长度相同,也与包装的 Headers 列表的长度相同。实际上,items()
方法仅返回包装的 Headers 列表的副本。
在Headers对象上调用str()
返回适合于作为 HTTP 响应 Headers 传输的格式化字符串。每个 Headers 均以其值放在一行中,并用冒号和空格分隔。每行以回车和换行符结尾,字符串以空行结尾。
Headers对象除了具有 Map 界面和格式设置Function外,还具有以下方法用于查询和添加多值 Headers 以及添加具有 MIME 参数的 Headers:
get_all
(* name *)- 返回命名 Headers 的所有值的列表。
返回的列表将按照它们在原始标题列表中出现或添加到此实例的 Sequences 进行排序,并且可能包含重复项。删除并重新插入的所有字段始终附加到标题列表中。如果不存在具有给定名称的字段,则返回一个空列表。
add_header
((* name , value ,** _ params *)- 添加一个(可能是多值的)标题,并pass关键字参数指定可选的 MIME 参数。
- name *是要添加的标题字段。关键字参数可用于设置 Headers 字段的 MIME 参数。每个参数必须是字符串或
None
。参数名称中的下划线将转换为破折号,因为破折号在 Python 标识符中是非法的,但是许多 MIME 参数名称都包含破折号。如果参数值是字符串,则以name="value"
的形式将其添加到 Headers 值参数中。如果为None
,则仅添加参数名称。 (这用于没有值的 MIME 参数.)用法示例:
h.add_header('content-disposition', 'attachment', filename='bud.gif')
上面将添加一个标题,如下所示:
Content-Disposition: attachment; filename="bud.gif"
20.4.3. wsgiref.simple_server –简单的 WSGI HTTP 服务器
该模块实现了一个简单的 HTTP 服务器(基于BaseHTTPServer),该服务器为 WSGI 应用程序服务。每个服务器实例在给定的主机和端口上服务单个 WSGI 应用程序。如果要在单个主机和端口上提供多个应用程序,则应创建一个 WSGI 应用程序,该应用程序分析PATH_INFO
来选择要为每个请求调用的应用程序。 (例如,使用wsgiref.util中的shift_path_info()
函数。)
wsgiref.simple_server.
make_server
(* host , port , app , server_class = WSGIServer , handler_class = WSGIRequestHandler *)- 创建一个新的 WSGI 服务器,监听* host 和 port ,接受 app 的连接。返回值是提供的 server_class 的实例,并将使用指定的 handler_class *处理请求。 * app *必须是 PEP 333定义的 WSGI 应用程序对象。
Example usage:
from wsgiref.simple_server import make_server, demo_app
httpd = make_server('', 8000, demo_app)
print "Serving HTTP on port 8000..."
# Respond to requests until process is killed
httpd.serve_forever()
# Alternative: serve one request, then exit
httpd.handle_request()
wsgiref.simple_server.
demo_app
(* environ , start_response *)- 该函数是一个小型但完整的 WSGI 应用程序,它返回一个包含消息“ Hello world!”的文本页面。以及* environ *参数中提供的键/值对的列表。这对于验证 WSGI 服务器(例如wsgiref.simple_server)是否能够正确运行简单的 WSGI 应用程序很有用。
-
- class *
wsgiref.simple_server.
WSGIServer
(* server_address , RequestHandlerClass *)
- 创建一个WSGIServer实例。 * server_address 应该是
(host,port)
Tuples,而 RequestHandlerClass *应该是将用于处理请求的BaseHTTPServer.BaseHTTPRequestHandler的子类。
- class *
通常不需要调用此构造函数,因为make_server()函数可以为您处理所有详细信息。
WSGIServer是BaseHTTPServer.HTTPServer的子类,因此它的所有方法(例如serve_forever()
和handle_request()
)都可用。 WSGIServer还提供了这些特定于 WSGI 的方法:
set_app
(应用程序)- 将可调用的* application *设置为将接收请求的 WSGI 应用程序。
get_app
( )- 返回当前设置的可调用应用程序。
但是,通常不需要使用这些其他方法,因为set_app()通常由make_server()调用,而get_app()主要是为了请求处理程序实例而存在。
-
- class *
wsgiref.simple_server.
WSGIRequestHandler
(* request , client_address , server *)
- 为给定的* request (即套接字), client_address (
(host,port)
Tuples)和 server *(WSGIServer实例)创建 HTTP 处理程序。
- class *
您无需直接创建此类的实例; WSGIServer对象会根据需要自动创建它们。但是,您可以继承该类并将其作为* handler_class *提供给make_server()函数。在子类中重写的一些可能相关的方法:
get_environ
( )- 返回包含请求的 WSGI 环境的字典。默认实现将复制WSGIServer对象的
base_environ
字典属性的内容,然后添加从 HTTP 请求派生的各种 Headers。每次对此方法的调用都应返回一个新字典,其中包含 PEP 333中指定的所有相关 CGI 环境变量。
- 返回包含请求的 WSGI 环境的字典。默认实现将复制WSGIServer对象的
get_stderr
( )- 返回应用作
wsgi.errors
流的对象。默认实现只是返回sys.stderr
。
- 返回应用作
handle
( )- 处理 HTTP 请求。缺省实现使用wsgiref.handlers类创建一个处理程序实例,以实现实际的 WSGI 应用程序接口。
20.4.4. wsgiref.validate — WSGI 一致性检查器
创建新的 WSGI 应用程序对象,框架,服务器或中间件时,使用wsgiref.validate验证新代码的一致性可能很有用。该模块提供了创建 WSGI 应用程序对象的Function,该Function验证 WSGI 服务器或网关与 WSGI 应用程序对象之间的通信,以检查双方的协议一致性。
请注意,该 Util 不能保证完全符合 PEP 333的要求;该模块中没有错误并不一定意味着不存在错误。但是,如果此模块确实产生错误,则实际上可以确定服务器或应用程序不是 100%兼容的。
该模块基于 Ian Bicking 的“ Python Paste”库中的paste.lint
模块。
wsgiref.validate.
validator
(* application *)- 包装* application 并返回一个新的 WSGI 应用程序对象。返回的应用程序会将所有请求转发到原始 application ,并将检查 application *和调用它的服务器都符合 WSGI 规范和 RFC 2616.
任何检测到的不符合项都会引发AssertionError;但是请注意,如何处理这些错误取决于服务器。例如,wsgiref.simple_server和其他基于wsgiref.handlers的服务器(不会覆盖错误处理方法以执行其他操作)将仅输出一条消息,指出发生了错误,并将回溯信息转储到sys.stderr
或其他错误流。
该包装器还可以使用warnings模块生成输出,以指示可疑但 PEP 333可能实际上并未禁止的行为。除非使用 Python 命令行选项或warnings API 禁止它们,否则任何此类警告都将被写入sys.stderr
(* not * wsgi.errors
,除非它们恰好是同Pair象)。
Example usage:
from wsgiref.validate import validator
from wsgiref.simple_server import make_server
# Our callable object which is intentionally not compliant to the
# standard, so the validator is going to break
def simple_app(environ, start_response):
status = '200 OK' # HTTP Status
headers = [('Content-type', 'text/plain')] # HTTP Headers
start_response(status, headers)
# This is going to break because we need to return a list, and
# the validator is going to inform us
return "Hello World"
# This is the application wrapped in a validator
validator_app = validator(simple_app)
httpd = make_server('', 8000, validator_app)
print "Listening on port 8000...."
httpd.serve_forever()
20.4.5. wsgiref.handlers –服务器/网关基本类
该模块提供用于实现 WSGI 服务器和网关的基本处理程序类。这些 Base Class 可以处理与 WSGI 应用程序进行通信的大部分工作,只要它们具有类似 CGI 的环境以及 Importing,输出和错误流即可。
- 类别
wsgiref.handlers.
CGIHandler
- pass
sys.stdin
,sys.stdout
,sys.stderr
和os.environ
的基于 CGI 的调用。当您拥有 WSGI 应用程序并希望将其作为 CGI 脚本运行时,这很有用。只需调用CGIHandler().run(app)
,其中app
是您希望调用的 WSGI 应用程序对象。
- pass
此类是BaseCGIHandler的子类,该子类将wsgi.run_once
设置为 true,将wsgi.multithread
设置为 false,并将wsgi.multiprocess
设置为 true,并且始终使用sys和os来获取必要的 CGI 流和环境。
-
- class *
wsgiref.handlers.
BaseCGIHandler
(* stdin , stdout , stderr , environ , multithread = True , multiprocess = False *)
- 与CGIHandler相似,但是不使用sys和os模块,而是显式指定 CGI 环境和 I/O 流。 * multithread 和 multiprocess *值用于为处理程序实例运行的任何应用程序设置
wsgi.multithread
和wsgi.multiprocess
标志。
- class *
此类是SimpleHandler的子类,旨在与 HTTP“起源服务器”以外的软件一起使用。如果您正在编写使用Status:
Headers 发送 HTTP 状态的网关协议实现(例如 CGI,FastCGI,SCGI 等),则您可能希望将其子类化,而不是SimpleHandler。
-
- class *
wsgiref.handlers.
SimpleHandler
(* stdin , stdout , stderr , environ , multithread = True , multiprocess = False *)
- 与BaseCGIHandler类似,但设计用于 HTTP 源服务器。如果您正在编写 HTTP 服务器实现,则可能要对此子类化,而不是BaseCGIHandler。
- class *
此类是BaseHandler的子类。它重写init(),get_stdin()
,get_stderr()
,add_cgi_vars()
,_write()
和_flush()
方法,以支持pass构造函数显式设置环境和流。提供的环境和流存储在stdin
,stdout
,stderr
和environ
属性中。
- 类别
wsgiref.handlers.
BaseHandler
- 这是用于运行 WSGI 应用程序的抽象 Base Class。每个实例将处理一个 HTTP 请求,尽管原则上您可以创建可用于多个请求的子类。
BaseHandler实例只有一种供外部使用的方法:
run
(* app *)- 运行指定的 WSGI 应用程序* app *。
在运行应用程序的过程中,所有其他BaseHandler方法都由该方法调用,因此主要存在以允许自定义过程。
在子类中必须重写以下方法:
_write
(* data *)- 缓冲字符串* data *以便传输到 Client 端。如果该方法实际传输数据也可以;当基础系统实际上具有这种区别时,BaseHandler只是将写操作和刷新操作分开以提高效率。
_flush
( )- 强制将缓冲的数据传输到 Client 端。此方法为空操作也可以(例如_write()实际发送数据)。
get_stdin
( )- 返回适合用作当前正在处理的请求的
wsgi.input
的 Importing 流对象。
- 返回适合用作当前正在处理的请求的
get_stderr
( )- 返回适合用作当前正在处理的请求的
wsgi.errors
的输出流对象。
- 返回适合用作当前正在处理的请求的
add_cgi_vars
( )- 将当前请求的 CGI 变量插入
environ
属性。
- 将当前请求的 CGI 变量插入
这里是您可能希望覆盖的其他一些方法和属性。但是,此列表只是一个摘要,并不包括可以覆盖的所有方法。在try创建自定义的BaseHandler子类之前,应查阅文档字符串和源代码以获取其他信息。
定制 WSGI 环境的属性和方法:
wsgi_multithread
- 用于
wsgi.multithread
环境变量的值。它在BaseHandler中默认为 true,但在其他子类中可能具有不同的默认值(或由构造函数设置)。
- 用于
wsgi_multiprocess
- 用于
wsgi.multiprocess
环境变量的值。它在BaseHandler中默认为 true,但在其他子类中可能具有不同的默认值(或由构造函数设置)。
- 用于
wsgi_run_once
wsgi.run_once
环境变量要使用的值。在BaseHandler中默认为 false,但是CGIHandler默认将其设置为 true。
os_environ
- 每个请求的 WSGI 环境中将包含的默认环境变量。默认情况下,这是导入wsgiref.handlers时的
os.environ
的副本,但是子类可以在类或实例级别创建自己的副本。请注意,字典应被视为只读,因为默认值在多个类和实例之间共享。
- 每个请求的 WSGI 环境中将包含的默认环境变量。默认情况下,这是导入wsgiref.handlers时的
server_software
- 如果设置了origin_server属性,则此属性的值将用于设置默认的
SERVER_SOFTWARE
WSGI 环境变量,并在 HTTP 响应中设置默认的Server:
Headers。对于不是 HTTP 源服务器的处理程序(例如BaseCGIHandler和CGIHandler),将忽略它。
- 如果设置了origin_server属性,则此属性的值将用于设置默认的
get_scheme
( )- 返回用于当前请求的 URL 方案。默认实现使用来自wsgiref.util的
guess_scheme()
函数根据当前请求的environ
变量猜测方案是“ http”还是“ https”。
- 返回用于当前请求的 URL 方案。默认实现使用来自wsgiref.util的
setup_environ
( )- 将
environ
属性设置为完全填充的 WSGI 环境。默认实现使用上述所有方法和属性,以及get_stdin(),get_stderr()和add_cgi_vars()方法以及wsgi_file_wrapper属性。只要origin_server属性为真值并且设置了server_software属性,它还将插入SERVER_SOFTWARE
键(如果不存在)。
- 将
定制异常处理的方法和属性:
log_exception
(* exc_info *)- 在服务器日志中记录* exc_info *Tuples。 * exc_info *是
(type, value, traceback)
Tuples。默认实现只是将回溯写到请求的wsgi.errors
流中并将其刷新。子类可以重写此方法,以更改格式或重新定位输出,将 traceback 邮件发送给 Management 员或采取其他任何认为合适的措施。
- 在服务器日志中记录* exc_info *Tuples。 * exc_info *是
traceback_limit
- 默认log_exception()方法输出的回溯中要包括的最大帧数。如果
None
,则包括所有帧。
- 默认log_exception()方法输出的回溯中要包括的最大帧数。如果
error_output
((* environ , start_response *)- 此方法是 WSGI 应用程序,用于为用户生成错误页面。仅在将头发送到 Client 端之前发生错误时才调用它。
此方法可以使用sys.exc_info()
访问当前错误信息,并在调用它时将其传递给* start_response *(如 PEP 333的“错误处理”部分所述)。
默认实现仅使用error_status,error_headers和error_body属性来生成输出页面。子类可以覆盖它,以产生更多的动态错误输出。
但是请注意,从安全角度来看,不建议向任何老用户吐出诊断信息。理想情况下,您必须执行一些特殊的操作才能启用诊断输出,这就是默认实现不包含任何内容的原因。
error_status
- 用于错误响应的 HTTP 状态。这应该是 PEP 333中定义的状态字符串;它默认为 500 个代码和消息。
error_headers
- 用于错误响应的 HTTPHeaders。如 PEP 333所述,这应该是 WSGI 响应头(
(name, value)
Tuples)的列表。默认列表仅将 Content Type 设置为text/plain
。
- 用于错误响应的 HTTPHeaders。如 PEP 333所述,这应该是 WSGI 响应头(
error_body
- 错误响应主体。这应该是 HTTP 响应正 Literals 符串。默认为纯文本,“发生服务器错误。请与 Management 员联系。”
PEP 333的“可选的特定于平台的文件处理”Function的方法和属性:
wsgi_file_wrapper
wsgi.file_wrapper
工厂或None
。此属性的默认值为wsgiref.util的FileWrapper
类。
sendfile
( )- 重写以实现特定于平台的文件传输。仅当应用程序的返回值是wsgi_file_wrapper属性指定的类的实例时,才调用此方法。如果它能够成功传输文件,则应返回一个真值,这样就不会执行默认的传输代码。此方法的默认实现只是返回一个假值。
其他方法和属性:
origin_server
此属性的默认值在BaseHandler中为 true,但在BaseCGIHandler和CGIHandler中为 false。
http_version
- 如果origin_server为 true,则此字符串属性用于将响应集的 HTTP 版本设置为 Client 端。默认为
"1.0"
。
- 如果origin_server为 true,则此字符串属性用于将响应集的 HTTP 版本设置为 Client 端。默认为
20.4.6. Examples
这是一个正在运行的“ Hello World” WSGI 应用程序:
from wsgiref.simple_server import make_server
# Every WSGI application must have an application object - a callable
# object that accepts two arguments. For that purpose, we're going to
# use a function (note that you're not limited to a function, you can
# use a class for example). The first argument passed to the function
# is a dictionary containing CGI-style environment variables and the
# second variable is the callable object (see PEP 333).
def hello_world_app(environ, start_response):
status = '200 OK' # HTTP Status
headers = [('Content-type', 'text/plain')] # HTTP Headers
start_response(status, headers)
# The returned object is going to be printed
return ["Hello World"]
httpd = make_server('', 8000, hello_world_app)
print "Serving on port 8000..."
# Serve until process is killed
httpd.serve_forever()