wsgiref

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_INFOQUERY_STRING变量被忽略。结果是请求所处理的应用程序对象的基本URI。

wsgiref.util.shift_path_info(environ)

将单个名称从中PATH_INFO切换SCRIPT_NAME并返回名称。该ENVIRON字典改性就地; 如果您需要保留原件PATH_INFOSCRIPT_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_HOSTSERVER_NAMESERVER_PORTREQUEST_METHODSCRIPT_NAMEPATH_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)元组)和serverWSGIServer实例)创建一个HTTP处理程序。

你不需要直接创建这个类的实例。它们会根据WSGIServer对象的需要自动创建。但是,您可以继承这个类并将其作为handler_class提供make_server()函数。一些可能相关的用于覆盖子类的方法:

get_environ()

返回包含请求的WSGI环境的字典。默认实现复制WSGIServer对象的base_environdictionary属性的内容,然后添加从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.lintIan Bicking的“Python Paste”库中的模块。

wsgiref.validate.validator(application)

包装应用程序并返回一个新的WSGI应用程序对象。返回的应用程序会将所有请求转发给原始应用程序,并将检查应用程序和调用它的服务器是否符合WSGI规范和RFC 2616。

任何检测到的不合格都会导致产生AssertionError; 但请注意,如何处理这些错误取决于服务器。例如,wsgiref.simple_server基于其他服务器的服务器wsgiref.handlers(不会覆盖错误处理方法来执行其他操作)只会输出错误已发生的消息,并将追溯转储到sys.stderr其他某个错误流。

该包装也可以使用该warnings模块生成输出以指示可疑的行为,但PEP 333实际上可能不会禁止该行为。除非它们被使用Python命令行选项或抑制warningsAPI,任何这样的警告将被写入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.stdinsys.stdoutsys.stderros.environ。当你有一个WSGI应用程序并且想把它作为一个CGI脚本运行时,这很有用。简单地调用CGIHandler().run(app)app你希望调用的WSGI应用程序对象在哪里。

这个类是它的一个子类,BaseCGIHandler它设置wsgi.run_once为true,wsgi.multithreadfalse和wsgi.multiprocesstrue,并且总是使用sysos获得必要的CGI流和环境。

class wsgiref.handlers.BaseCGIHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)

与此类似CGIHandler,但不是使用sysos模块,而是显式指定CGI环境和I / O流。在多线程多进程值被用来设置wsgi.multithreadwsgi.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()方法以支持明确设置环境,通过构造流。所提供的环境和流被存储在stdinstdoutstderr,和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_SOFTWAREWSGI环境变量,并且还可以Server:在HTTP响应中设置默认标题。对于不是HTTP原始服务器的处理程序(例如BaseCGIHandlerCGIHandler),它将被忽略。

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_statuserror_headerserror_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()

扫码关注云+社区

领取腾讯云代金券