wsgiref
wsgiref — WSGI Utilities and Reference Implementation
2.5版本中的新功能。
Web服务器网关接口(WSGI)是Web服务器软件和用Python编写的Web应用程序之间的标准接口。拥有标准接口可以轻松使用支持WSGI和多个不同Web服务器的应用程序。
只有Web服务器和编程框架的作者需要知道WSGI设计的每个细节和角落案例。您不需要了解WSGI的每个细节,只需安装WSGI应用程序或使用现有框架编写Web应用程序即可。
wsgiref
是WSGI规范的参考实现,可用于将WSGI支持添加到Web服务器或框架。它提供了用于操纵WSGI环境变量和响应头的实用程序,用于实现WSGI服务器的基类,为WSGI应用程序提供服务的演示HTTP服务器以及用于检查WSGI服务器和应用程序是否符合WSGI规范(PEP 333
)的验证工具。
有关WSGI的更多信息,请参阅https://wsgi.readthedocs.org/以及指向教程和其他资源的链接。
1. wsgiref.util - WSGI环境实用程序
该模块提供了多种用于WSGI环境的实用程序功能。WSGI环境是一个包含PEP 333中
描述的HTTP请求变量的字典。所有采用environ
参数的函数都需要提供符合WSGI的字典; 详细规范请参阅PEP 333
。
wsgiref.util.guess_scheme(environ)
wsgi.url_scheme
通过检查environ
字典中的HTTPS
环境变量来返回是否应该是“http”或“https” 的猜测。返回值是一个字符串。
创建包装CGI的网关或类似CGI的协议(如FastCGI)时,此功能很有用。通常,HTTPS
当通过SSL接收请求时,提供此类协议的服务器将包含一个值为“1”“是”或“开” 的变量。所以,如果找到这样的值,这个函数返回“https”,否则返回“http”。
wsgiref.util.request_uri(environ, include_query=1)
使用PEP 333
的“URL Reconstruction”部分中找到的算法返回完整的请求URI,可选地包括查询字符串。如果include_query
为false,则查询字符串不包含在生成的URI中。
wsgiref.util.application_uri(environ)
类似request_uri()
,除了PATH_INFO
和QUERY_STRING
变量被忽略。结果是请求所处理的应用程序对象的基本URI。
wsgiref.util.shift_path_info(environ)
将单个名称从中PATH_INFO
切换SCRIPT_NAME
并返回名称。该ENVIRON
字典改性
就地; 如果您需要保留原件PATH_INFO
或SCRIPT_NAME
完好无损,请使用副本。
如果没有剩余路径段PATH_INFO
,则返回None。
通常,此例程用于处理请求URI路径的每个部分,例如将路径视为一系列字典键。此例程修改传入的环境以使其适用于调用位于目标URI处的另一个WSGI应用程序。例如,如果WSGI应用程序位于/foo
,请求URI路径为/foo/bar/baz
,并且WSGI应用程序处于/foo
调用状态shift_path_info()
,则它将收到字符串“bar”,并且环境将更新为适合传递给WSGI应用程序/foo/bar
。也就是说,SCRIPT_NAME
将会从/foo
变为/foo/bar
,并将PATH_INFO
从/bar/baz
变为/baz
。
当PATH_INFO
只是一个“/”时,这个例程返回一个空字符串并附加一个尾部斜线SCRIPT_NAME
,即使通常忽略空路段,并且SCRIPT_NAME
通常不以斜线结尾。这是有意的行为,以确保应用程序可以区分以使用此例程进行对象遍历时/x
结束的URI之间的差异/x/
。
wsgiref.util.setup_testing_defaults(environ)
更新ENVIRON
琐碎的默认设置进行测试。
这个程序增加了对WSGI所需的各种参数,包括HTTP_HOST
,SERVER_NAME
,SERVER_PORT
,REQUEST_METHOD
,SCRIPT_NAME
,PATH_INFO
,和所有的PEP 333
-defined 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')]
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()
除上述环境功能外,该wsgiref.util
模块还提供了这些杂项实用程序:
wsgiref.util.is_hop_by_hop(header_name)
如果'header_name'是RFC 2616
定义的HTTP / 1.1“逐跳”标头,则返回true 。
class wsgiref.util.FileWrapper(filelike, blksize=8192)
将文件类对象转换为迭代器的包装器。所得到的对象支持__getitem__()
和__iter__()
迭代的风格,对于与Python 2.1和Jython兼容。当对象被遍历,可选表示blksize
参数将被重复传递给类文件
对象的read()
方法来获取字符串屈服。当read()
返回一个空字符串时,迭代结束并且不可恢复。
如果filelike
有一个close()
方法,返回的对象也会有一个close()
方法,并且在调用时会调用类文件
对象的close()
方法。
用法示例:
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
2. wsgiref.headers - WSGI响应头文件工具
这个模块提供了一个类,Headers
用于使用类似映射的接口方便地处理WSGI响应头。
class wsgiref.headers.Headers(headers)
创建一个类似映射的对象封装标头
,它必须是PEP 333中
描述的标头
名称/值元组列表。对新Headers
对象所做的任何更改都将直接更新其创建的标题
列表。
Headers
对象支持典型映射操作,包括__getitem__()
,get()
,__setitem__()
,setdefault()
,__delitem__()
,__contains__()
和has_key()
。对于这些方法中的每一个,关键是标头名称(不区分大小写处理),并且该值是与该标头名称关联的第一个值。设置标题将删除该标题的所有现有值,然后在包装标题列表的末尾添加一个新值。通常会保留标题的现有订单,并将新标题添加到包装列表的末尾。
与字典不同,Headers
当您尝试获取或删除不在包装标题列表中的密钥时,对象不会引发错误。获取不存在的头只是返回None
,并且删除不存在的头不会执行任何操作。
Headers
对象也支持keys()
,values()
和items()
方法。该名单由归国keys()
,并items()
可以包括相同的密钥不止一次,如果有一个多值的头。的len()
一个的Headers
目的是相同的其长度items()
,这是一样的缠绕头列表的长度。实际上,该items()
方法只是返回包装标题列表的副本。
调用str()
一个Headers
对象返回一个适合作为HTTP响应头传输的格式化字符串。每个标题都放在一行上,并用冒号和空格分隔。每行都以回车符和换行符结束,字符串以空行结束。
除了映射接口和格式化功能外,Headers
对象还具有以下用于查询和添加多值标题的方法,以及用于添加具有MIME参数的标题的方法:
get_all(name)
返回指定标题的所有值的列表。
返回的列表将按照它们出现在原始标题列表中的顺序排序,或者添加到此实例中,并可能包含重复项。任何删除并重新插入的字段都会附加到标题列表中。如果给定名称不存在字段,则返回空列表。
add_header(name, value, **_params)
添加一个(可能是多值的)头,其中包含通过关键字参数指定的可选MIME参数。
名称
是要添加的标题字段。关键字参数可用于为标题字段设置MIME参数。每个参数必须是字符串或None
。参数名称
中的下划线将转换为破折号,因为破折号在Python标识符中是非法的,但许多MIME参数名称
都包含破折号。如果参数值是一个字符串,则将其添加到表单中的标题值参数中name="value"
。如果是None
,则只添加参数名称
。(这用于没有值的MIME参数。)示例用法:
h.add_header('content-disposition', 'attachment', filename='bud.gif')
以上将添加一个如下所示的标题:
Content-Disposition: attachment; filename="bud.gif"
3. wsgiref.simple_server - 一个简单的WSGI HTTP服务器
这个模块实现了一个简单的HTTP服务器(基于BaseHTTPServer
)为WSGI应用程序提供服务。每个服务器实例在给定主机和端口上提供单个WSGI应用程序。如果您想在单个主机和端口上提供多个应用程序,则应该创建一个WSGI应用程序,PATH_INFO
该应用程序可以解析以选择为每个请求调用哪个应用程序。(例如,使用shift_path_info()
来自的功能wsgiref.util
。)
wsgiref.simple_server.make_server(host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler)
创建一个监听主机
和端口
的新WSGI服务器,接受应用程序的
连接。返回值是提供的server_class的
一个实例,并将使用指定的handler_class
处理请求。app
必须是一个WSGI应用程序对象,如PEP 333
所定义。
用法示例:
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)
元组,并且RequestHandlerClass
应该BaseHTTPServer.BaseHTTPRequestHandler
是用于处理请求的子类。
您通常不需要调用此构造函数,因为该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)
为给定请求
(即套接字),client_address
(一个(host,port)
元组)和server
(WSGIServer
实例)创建一个HTTP处理程序。
你不需要直接创建这个类的实例。它们会根据WSGIServer
对象的需要自动创建。但是,您可以继承这个类并将其作为handler_class提供
给make_server()
函数。一些可能相关的用于覆盖子类的方法:
get_environ()
返回包含请求的WSGI环境的字典。默认实现复制WSGIServer
对象的base_environ
dictionary属性的内容,然后添加从HTTP请求派生的各种头文件。对该方法的每次调用应该返回一个新的字典,其中包含PEP 333中
指定的所有相关CGI环境变量。
get_stderr()
返回应该用作wsgi.errors
流的对象。默认实现只是返回sys.stderr
。
handle()
处理HTTP请求。默认实现使用wsgiref.handlers
类创建一个处理程序实例来实现实际的WSGI应用程序接口。
4. wsgiref.validate - WSGI一致性检查器
在创建新的WSGI应用程序对象,框架,服务器或中间件时,使用新的代码一致性验证可能很有用wsgiref.validate
。该模块提供了一个函数,用于创建验证WSGI服务器或网关与WSGI应用程序对象之间通信的WSGI应用程序对象,以检查双方是否符合协议。
请注意,此实用程序不能保证完全符合PEP 333
; 这个模块没有错误并不一定意味着错误不存在。但是,如果此模块确实产生错误,那么几乎可以确定服务器或应用程序不是100%兼容的。
该模块基于paste.lint
Ian Bicking的“Python Paste”库中的模块。
wsgiref.validate.validator(application)
包装应用程序
并返回一个新的WSGI应用程序
对象。返回的应用程序
会将所有请求转发给原始应用程序
,并将检查应用程序
和调用它的服务器是否符合WSGI规范和RFC 2616。
任何检测到的不合格都会导致产生AssertionError
; 但请注意,如何处理这些错误取决于服务器。例如,wsgiref.simple_server
基于其他服务器的服务器wsgiref.handlers
(不会覆盖错误处理方法来执行其他操作)只会输出错误已发生的消息,并将追溯转储到sys.stderr
其他某个错误流。
该包装也可以使用该warnings
模块生成输出以指示可疑的行为,但PEP 333
实际上可能不会禁止该行为。除非它们被使用Python命令行选项或抑制warnings
API,任何这样的警告将被写入sys.stderr
(未
wsgi.errors
,除非它们碰巧是相同的对象)。
用法示例:
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()
5. wsgiref.handlers - 服务器/网关基类
该模块为实现WSGI服务器和网关提供基本处理程序类。这些基类处理与WSGI应用程序通信的大部分工作,只要它们具有类CGI环境以及输入,输出和错误流。
class wsgiref.handlers.CGIHandler
通过基于CGI的调用sys.stdin
,sys.stdout
,sys.stderr
和os.environ
。当你有一个WSGI应用程序并且想把它作为一个CGI脚本运行时,这很有用。简单地调用CGIHandler().run(app)
,app
你希望调用的WSGI应用程序对象在哪里。
这个类是它的一个子类,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流。在多线程
和多进程
值被用来设置wsgi.multithread
和wsgi.multiprocess
标志由处理实例中运行的所有应用程序。
这个类是SimpleHandler
打算与HTTP“原始服务器”以外的软件一起使用的子类。如果您正在编写使用Status:
头来发送HTTP状态的网关协议实现(例如CGI,FastCGI,SCGI等),那么您可能希望将其替换为子类SimpleHandler
。
class wsgiref.handlers.SimpleHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)
BaseCGIHandler
与HTTP源服务器类似,但设计用于HTTP源服务器。如果你正在编写一个HTTP服务器实现,你可能想要继承它而不是BaseCGIHandler
。
这个类是一个子类BaseHandler
。它覆盖了__init__()
,get_stdin()
,get_stderr()
,add_cgi_vars()
,_write()
,和_flush()
方法以支持明确设置环境,通过构造流。所提供的环境和流被存储在stdin
,stdout
,stderr
,和environ
属性。
class wsgiref.handlers.BaseHandler
这是运行WSGI应用程序的抽象基类。每个实例将处理单个HTTP请求,但原则上,您可以创建一个可用于多个请求的子类。
BaseHandler
实例只有一种用于外部使用的方法:
run(app)
运行指定的WSGI应用程序app
。
所有其他BaseHandler
方法在运行应用程序的过程中都由此方法调用,因此主要用于定制过程。
必须在子类中覆盖以下方法:
_write(data)
缓冲字符串数据
以传输给客户端。如果这种方法实际传输数据
,这没关系; BaseHandler
只是在底层系统实际上具有这种区别时,才将写入和刷新操作分开以提高效率。
_flush()
强制缓冲数据传输到客户端。如果这种方法是无操作的(即,如果_write()
实际发送数据),那没关系。
get_stdin()
返回适合用作wsgi.input
当前正在处理的请求的输入流对象。
get_stderr()
返回适合用作wsgi.errors
当前正在处理的请求的输出流对象。
add_cgi_vars()
将当前请求的CGI变量插入到environ
属性中。
以下是您可能希望覆盖的一些其他方法和属性。然而,这个列表只是一个总结,并不包括可以被覆盖的每个方法。在尝试创建自定义BaseHandler
子类之前,您应该查阅文档字符串和源代码以获取更多信息。
定制WSGI环境的属性和方法:
wsgi_multithread
要用于wsgi.multithread
环境变量的值。它默认为true BaseHandler
,但在其他子类中可能有不同的默认值(或由构造函数设置)。
wsgi_multiprocess
要用于wsgi.multiprocess
环境变量的值。它默认为true BaseHandler
,但在其他子类中可能有不同的默认值(或由构造函数设置)。
wsgi_run_once
要用于wsgi.run_once
环境变量的值。它默认为false BaseHandler
,但CGIHandler
默认设置为true。
os_environ
要包含在每个请求的WSGI环境中的默认环境变量。默认情况下,这是导入os.environ
时的副本wsgiref.handlers
,但子类可以在类或实例级别创建它们自己的副本。请注意,字典应该被认为是只读的,因为默认值是在多个类和实例之间共享的。
server_software
如果origin_server
设置了该属性,则使用此属性的值来设置默认的SERVER_SOFTWARE
WSGI环境变量,并且还可以Server:
在HTTP响应中设置默认标题。对于不是HTTP原始服务器的处理程序(例如BaseCGIHandler
和CGIHandler
),它将被忽略。
get_scheme()
返回用于当前请求的URL方案。默认实现使用guess_scheme()
函数从wsgiref.util
当前请求的environ
变量中猜测该方案是“http”还是“https” 。
setup_environ()
将该environ
属性设置为完全填充的WSGI环境。默认实现使用上述所有方法和属性,再加上get_stdin()
,get_stderr()
以及add_cgi_vars()
方法和wsgi_file_wrapper
属性。SERVER_SOFTWARE
如果不存在,它也会插入一个密钥,只要该origin_server
属性是一个真实值并且该server_software
属性已设置。
用于自定义异常处理的方法和属性:
log_exception(exc_info)
将exc_info
元组记录到服务器日志中。exc_info
是一个(type, value, traceback)
元组。默认实现简单地将回溯写入请求的wsgi.errors
流并刷新它。子类可以重写此方法来更改格式或重定目标输出,将回溯邮件发送给管理员,或者其他任何可能被认为合适的操作。
traceback_limit
缺省log_exception()
方法输出的回溯中包含的最大帧数。如果None
包含所有框架。
error_output(environ, start_response)
此方法是一个WSGI应用程序,为用户生成错误页面。只有在标题发送到客户端之前发生错误时才会调用它。
此方法可以使用当前的错误信息sys.exc_info()
,并在调用时将该信息传递给start_response
(如PEP 333
的“错误处理”部分中所述)。
默认的实现只是使用的error_status
,error_headers
和error_body
属性生成输出页面。子类可以覆盖它以产生更多的动态错误输出。
但是,请注意,从安全角度不建议将诊断信息吐出给任何旧用户; 理想情况下,您应该做一些特殊的事情来启用诊断输出,这就是为什么默认实现不包含任何内容。
error_status
用于错误响应的HTTP状态。这应该是PEP 333中
定义的状态字符串; 它默认为500代码和消息。
error_headers
用于错误响应的HTTP标头。这应该是一个WSGI响应头((name, value)
元组)的列表,如PEP 333所述
。默认列表只是将内容类型设置为text/plain
。
error_body
错误响应正文。这应该是一个HTTP响应正文字符串。它默认为纯文本,“发生服务器错误。请联系管理员。“
PEP 333
的“可选平台特定文件处理”功能的方法和属性:
wsgi_file_wrapper
一个wsgi.file_wrapper
工厂,或None
。此属性的默认值是FileWrapper
来自的类wsgiref.util
。
sendfile()
重写以实现平台特定的文件传输。只有当应用程序的返回值是由wsgi_file_wrapper
属性指定的类的实例时才调用此方法。如果它能够成功传输文件,它应该返回一个真值,以便默认的传输代码不会被执行。此方法的默认实现仅返回一个假值。
其他方法和属性:
origin_server
如果处理程序的该属性应该设置为一个真正的价值_write()
和_flush()
被用来直接传达给客户,而不是通过想要在一个特殊的HTTP状态一类CGI网关协议Status:
报头。
该属性的默认值为true BaseHandler
,但在BaseCGIHandler
和中为false CGIHandler
。
http_version
如果origin_server
为true,则使用此字符串属性来设置为客户端设置的响应的HTTP版本。它默认为"1.0"
。
6.例子
这是一个工作的“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()