wsgirefWSGI实用程序和参考实现


Web服务器网关接口(WSGI)是Web服务器软件和用Python编写的Web应用程序之间的标准接口。使用标准接口可以很容易地使用支持WSGI的应用程序和许多不同的Web服务器.

只有Web服务器和编程框架的作者需要了解WSGI设计的每个细分案例。您不需要了解WSGI的每个细节只是为了安装WSGI应用程序或使用现有框架编写Web应用程序.

wsgiref是WSGI规范的参考实现,可用于向Web添加WSGI支持服务器或框架。它提供了用于操作WSGI环境变量和响应头的实用程序,用于实现WSGI服务器的基类,为WSGI应用程序提供服务的演示HTTP服务器,以及用于检查WSGI服务器和应用程序是否符合WSGI规范的验证工具( PEP 3333).

有关WSGI的更多信息,请参阅wsgi.readthedocs.io,以及linksto教程和其他资源.

wsgiref.util – WSGI环境实用程序

此模块提供了多种实用程序用于处理WSGIenvironments的函数。WSGI环境是包含HTTP请求变量的字典,如 PEP 3333 中所述。所有采用environ参数的函数都需要提供符合WSGI的字典;请看 PEP 3333 详细说明.

wsgiref.util.guess_scheme (environ)

回想一下是否wsgi.url_scheme应该是“http”或“https”,通过检查HTTPS字典中的environ环境变量。其中的值是一个字符串.

这个函数在创建包装CGI或类似CGI的协议(如FastCGI)的网关时很有用。通常,提供此类协议的服务器将包含HTTPS变量值为“1”“是”,或者当通过SSL接收请求时为“on”。所以,如果找到这样的值,这个函数返回“https”,否则返回“http”

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

使用在 PEP 3333 的“URL Reconstruction”部分中找到的算法,返回完整的请求URI,可选地包括查询字符串。如果include_query如果是,则查询字符串不包含在生成的URI中.

wsgiref.util.application_uri(environ)

request_uri()类似,除了PATH_INFOQUERY_STRING变量被忽略。结果是请求所解决的应用程序对象的基URI .

wsgiref.util.shift_path_infoenviron

从转换单个名称PATH_INFOSCRIPT_NAME并返回名称.environ字典是modified就地;如果你需要保留原件PATH_INFOSCRIPT_NAME完整地使用副本

如果PATH_INFO, None中没有剩余的路径段则返回

通常,此例程用于处理请求URI路径的每个部分,例如将路径视为一系列字典键。此例程修改传入的环境,使其适合调用位于目标URI的另一个WSGI应用程序。例如,如果/foo,请求URI路径为/foo/bar/baz,而/foo的WSGI应用程序调用shift_path_info(),它将收到字符串“bar”,并且环境将被更新为适合传递到/foo/bar的WSGI应用程序。也就是说,SCRIPT_NAME将从/foo改为/foo/barPATH_INFO将从/bar/baz更改为/baz.

PATH_INFO只是一个“/”时,此例程返回一个空字符串并向SCRIPT_NAME发送一个尾部斜杠,即使空路径段通常被忽略,并且SCRIPT_NAME通常不会以斜线结尾。这是有意的行为,以确保应用程序能够区分以/x结尾的URI与以/x/使用此程序进行对象遍历时

wsgiref.util.setup_testing_defaultsenviron

更新environ用于测试目的的普通默认值.

此例程添加了WSGI所需的各种参数,包括HTTP_HOST,SERVER_NAME, SERVER_PORT, REQUEST_METHOD, SCRIPT_NAME,PATH_INFO,以及所有 PEP 3333 – 定义wsgi.*变量。Itonly提供默认值,并不替换这些变量的任何现有设置.

此例程旨在使WSGI服务器和应用程序的单元测试更容易设置虚拟环境。实际的WSGIservers或应用程序不应该使用它,因为数据是假的!

用法示例:

from wsgiref.util import setup_testing_defaultsfrom 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_defaultsdef 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 retwith make_server("", 8000, simple_app) as httpd:    print("Serving on port 8000...")    httpd.serve_forever()

除了上面的环境函数之外,wsgiref.util module还提供了这些杂项实用程序

wsgiref.util.is_hop_by_hopheader_name

如果’header_name’是HTTP / 1.1“Hop-by-Hop”标题,则返回true,如RFC 2616 .

class wsgiref.util.FileWrapperfilelike, blksize=8192

一个将类文件对象转换为迭代器。生成的对象支持__getitem__()__iter__()迭代样式,与Python 2.1和Jython兼容。当对象被迭代时,可选的blksize参数将被重复传递给filelike对象的read()方法以获得产生的字节串。当read()返回一个空的字节串时,迭代结束并且不可恢复.

如果filelike有一个close()方法,返回的对象也将有一个close()方法,它会在调用时调用filelike对象的close()方法.

示例用法:

from io import StringIOfrom wsgiref.util import FileWrapper# We"re using a StringIO-buffer for as the file-like objectfilelike = StringIO("This is an example file-like object"*10)wrapper = FileWrapper(filelike, blksize=5)for chunk in wrapper:    print(chunk)

wsgiref.headersWSGI响应头工具

这个模块提供了一个单独的类Headers,用于使用类似映射的界面方便地操作WSGI响应头.

class wsgiref.headers.Headers ( [headers]

创建一个包含headers的映射式对象,它必须是中描述的headername / value元组列表PEP 3333 headers的默认值是空列表.

Headers对象支持典型的映射操作,包括__getitem__(), get(), __setitem__(), setdefault(),__delitem__()__contains__()。对于每个方法,键是标题名称(不区分大小写),value是与该标题名称关联的第一个值。设置标题会删除该标题的任何现有值,然后在包装标题列表的末尾添加一个新值。通常会维护标头的现有顺序,并将新标头添加到包装列表的末尾.

与字典不同,Headers当您尝试获取或删除密钥时,对象不会引发错误不在包装的标题列表中。获取一个不存在的头只返回None,删除一个不存在的头没有任何东西.

Headers对象也支持keys(), values()items()方法。如果存在多值标头,则keys()items()返回的列表可以多次包含相同的密钥。len()对象的Headersitems()的长度相同,这与包装头列表的长度相同。事实上,items()方法只返回包装标题列表的副本.

调用bytes()Headers对象上返回一个格式化的字节串,以便作为HTTP响应头传输。每个标题都放在aline上,其值由冒号和空格分隔。每一行都由一个回车符和换行符终止,而bytestring以ablank行终止.

除了它们的映射接口和格式化功能外,Headers对象还有以下查询方法并添加多值头,并添加带有MIME参数的头:

get_allname

返回指定头的所有值的列表.

返回的列表将按照它们在原始标题列表中出现的顺序排序,或者已添加到此实例中,并且可能包含重复项。删除并重新插入的任何字段始终附加到标题列表中。如果存在具有给定名称的nofield,则返回一个空列表.

add_header (name, value, **_params)

添加一个(可能是多值的)标头,并通过关键字参数指定可选的MIME参数.

name是要添加的标头字段。关键字参数可用于为标题字段设置MIME参数。每个参数必须是一个字符串或None。参数名称中的下划线转换为破折号,因为破折号在Python标识符中是非法的,但许多MIME参数名称包括破折号。如果参数值是一个字符串,它将被添加到表格name="value"中的标题值参数中。如果是None,则只添加参数名称。(这用于没有值的MIME参数。)示例用法:

h.add_header("content-disposition", "attachment", filename="bud.gif")

以上将添加如下所示的标题:

Content-Disposition: attachment; filename="bud.gif"

版本3.5更改:headers参数是可选的.

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

这个模块实现了一个简单的HTTP服务器(基于http.server)提供WSGI应用程序。每个服务器实例在给定主机和端口上提供单个WSGI应用程序。如果要在单个主机和端口上提供多个应用程序,则应创建一个解析PATH_INFO以选择为每个请求调用哪个应用程序。(例如,使用shift_path_info()功能wsgiref.util。)

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

创建一个新的WSGI服务器,监听hostport,接受app的连接。返回值是提供的server_class的一个实例,并使用指定的handler_class. app必须是一个WSGIapplication对象,由PEP 3333 .

用法示例:

from wsgiref.simple_server import make_server, demo_appwith make_server("", 8000, demo_app) as httpd:    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_appenviron, start_response

这个函数是一个小而完整的WSGI应用程序,它返回一个包含消息“Hello world!”的文本页面以及environ参数。它对于验证WSGI服务器很有用(例如wsgiref.simple_server)能够正确运行一个简单的WSGI应用程序

class wsgiref.simple_server.WSGIServerserver_address, RequestHandlerClass

创建一个 WSGIServer实例。server_address应该是(host,port)tuple和RequestHandlerClass应该是http.server.BaseHTTPRequestHandler的子类,将用于处理请求.

你通常不需要调用这个构造函数,如make_server()函数可以为你处理所有细节.

WSGIServerhttp.server.HTTPServer的子类,所以它的所有方法(例如serve_forever()handle_request())都是可用的。WSGIServer还提供了这些特定于WSGI的方法:

set_appapplication

将可调用的application设置为将接收请求的WSGI应用程序.

get_app ()

返回当前设置的应用程序可调用

但是,通常情况下,您不需要使用这些额外的方法,如set_app()通常由make_server()调用,而get_app()主要是为了请求处理程序实例的存在而存在.

class wsgiref.simple_server.WSGIRequestHandler (request, client_address, server)

为给定的request创建一个HTTP处理程序(即套接字),client_address(host,port)元组)和serverWSGIServer instance).

您不需要直接创建此类的实例;它们根据需要自动创建WSGIServer对象。但是,您可以将此类子类化并将其作为handler_class提供给make_server()函数。一些可能相关的覆盖小班的方法:

get_environ

返回包含请求的WSGI环境的字典。defaultimplementation复制WSGIServer对象的内容base_environ字典属性,然后添加从HTTP请求派生的各种标头。每次调用此方法都应返回一个新的字典,其中包含PEP 3333 .

get_stderr

返回应该用作wsgi.errors流的对象。defaultimplementation只返回sys.stderr.

handle

处理HTTP请求。默认实现使用wsgiref.handlers类创建一个处理程序实例来实现实际的WSGI应用程序接口.

wsgiref.validate – WSGI一致性检查器

在创建新的WSGI应用程序对象,框架,服务器或中间件时,使用wsgiref.validate。此模块提供了一个函数,用于创建WSGIapplication对象,以验证WSGI服务器或网关与WSGI应用程序对象之间的通信,以检查双方的协议兼容性.

请注意,此实用程序不保证完整 PEP 3333 合规性;此模块中的错误并不一定意味着错误确实存在。但是,如果此模块确实产生错误,那么实际上确定服务器或应用程序不是100%兼容的.

这个模块基于Ian Bicking的“PythonPaste”库中的paste.lint模块.

wsgiref.validate.validator (application)

包裹application并返回一个新的WSGI应用程序对象。返回的应用程序会将所有请求转发到原来的application,并检查application并且调用它的服务器符合WSGI规范和 RFC 2616 .

任何检测到的不符合都会导致AssertionError被提出;但请注意,这些错误的处理方式取决于服务器。例如,wsgiref.simple_server和基于wsgiref.handlers(不会将错误处理方法覆盖到其他地方)只会输出一条错误发生的消息,并将回溯转发到sys.stderr或其他一些错误流.

这个包装器也可以使用warnings模块来表示有问题但可能实际上不被​​禁止的行为PEP 3333 。除非使用Python命令行选项或warnings API来抑制它们,否则任何此类警告都将写入sys.stderrnot wsgi.errors,除非它们恰好是同一对象).

用法示例:

from wsgiref.validate import validatorfrom wsgiref.simple_server import make_server# Our callable object which is intentionally not compliant to the# standard, so the validator is going to breakdef 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 b"Hello World"# This is the application wrapped in a validatorvalidator_app = validator(simple_app)with make_server("", 8000, validator_app) as httpd:    print("Listening on port 8000....")    httpd.serve_forever()

wsgiref.handlers– 服务器/网关基类

此模块提供用于实现WSGI服务器和网关的基本处理程序类。这些基类处理与aWSGI应用程序通信的大部分工作,只要它们在内部输出,输出和错误流中被赋予类似CGI的环境.

class wsgiref.handlers.CGIHandler

基于CGI的调用sys.stdin, sys.stdout, sys.stderros.environ。当您拥有WSGI应用程序并希望作为CGI脚本运行时,这非常有用。只需调用CGIHandler().run(app),其中app是你想要调用的WSGI应用程序对象.

这个类是BaseCGIHandler设置wsgi.run_once为真,wsgi.multithread假,和wsgi.multiprocess为真,总是使用sysos获得必要的CGI流和环境

class wsgiref.handlers.IISCGIHandler

CGIHandler,在部署onMicrosoft的IIS Web服务器时使用,而没有设置配置allowPathInfooption(IIS> = 7)或配置数据库allowPathInfoForScriptMappings(IIS< 7).

默认情况下,IIS给出PATH_INFO在前面重复SCRIPT_NAME,导致希望实现路由的WSGI应用程序出现问题。这个处理程序剥离任何这样的重复路径.

IIS可以配置为传递正确的PATH_INFO,但这会导致另一个错误,其中PATH_TRANSLATED是错的。幸运的是,这个变量被使用,WSGI无法保证。但是在IIS< 7上,这些只能在vhost级别上进行,影响所有其他脚本映射,其中许多在暴露于PATH_TRANSLATED bug时会中断。因此,IIS< 7几乎从未部署过固定。(即使IIS7也使用它,因为它仍然没有UI。)

CGI代码无法判断选项是否已设置,因此提供了一个单独的处理程序类。它的使用方式与CGIHandler相同,即调用IISCGIHandler().run(app),其中app是你想调用的WSGI应用程序对象.

新版本3.2.

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

CGIHandler类似,但不是使用sysos modules,CGI环境和I / O流是明确指定的.multithreadmultiprocess值用于设置wsgi.multithreadwsgi.multiprocess标志处理程序实例运行的任何应用程序

这个类是SimpleHandler打算用于HTTP“原始服务器”以外的软件。如果您正在编写一个使用Status:标头发送HTTP状态的网关协议实现(例如CGI,FastCGI,SCGI等),您可能希望将其子类化为SimpleHandler.

class wsgiref.handlers.SimpleHandlerstdin, stdout, stderr, environ, multithread=True, multiprocess=False

BaseCGIHandler类似,但设计用于HTTP原始服务器。如果您正在编写HTTP服务器实现,您可能希望将其子类化而不是BaseCGIHandler.

此类是BaseHandler的子类。它会覆盖__init__(), get_stdin(), get_stderr(), add_cgi_vars(),_write()_flush()方法,以支持通过构造函数显式设置环境和流。提供的环境和流存储在stdin, stdout, stderrenviron属性

write() stdout的方法应该写完全,就像io.BufferedIOBase.

class wsgiref.handlers.BaseHandler

这是一个用于运行WSGI应用程序的抽象基类。每个实例都会处理一个HTTP请求,虽然原则上你可以创建可以为多个请求重用的asubclass .

BaseHandler实例只有一个外部使用的方法:

runapp

运行指定的WSGI应用程序,app.

所有其他BaseHandler方法在运行应用程序的过程中由此方法调用,因此主要用于允许自定义进程.

必须在子类中重写以下方法:

_writedata

缓冲字节data以传输到客户端。如果这种方法实际传输数据也没关系;BaseHandler当底层系统实际上有这样的区别时,只需将写入和刷新操作分开以获得更高的效率.

_flush ( )

强制缓冲数据传输到客户端。如果这种方法是无操作的话也没关系(即如果_write()实际发送数据).

get_stdin

返回一个输入流对象,适合用作当前正在处理的请求的wsgi.input.

get_stderr()

返回一个适合使用的输出流对象作为wsgi.errors当前正在处理的请求.

add_cgi_vars ()

将当前请求的CGI变量插入到environ属性中

以下是您可能希望覆盖的一些其他方法和属性。但是,此列表只是一个摘要,并不包括可以覆盖的每个方法。在尝试创建自定义的BaseHandlersubclass.

用于自定义WSGI环境的属性和方法:

wsgi_multithread

用于wsgi.multithread环境变量。它在中默认为真BaseHandler,但在其他子类中可能有不同的默认值(orbe由构造函数设置).

wsgi_multiprocess

用于wsgi.multiprocess环境变量。它在中默认为真BaseHandler,但在其他子类中可能有不同的默认值(orbe由构造函数设置).

wsgi_run_once

用于wsgi.run_once环境变量的值。在BaseHandler中它是假的,但CGIHandler默认情况下设置它.

os_environ

每个请求的WSGI环境中包含的默认环境变量。默认情况下,这是导入os.environwsgiref.handlers的副本,但是子类可以在类或实例级别创建自己的副本。请注意,字典应该被认为是只读的,因为默认值是在多个类和实例之间共享的.

server_software

如果设置了origin_server属性,则使用此属性的值来设置默认值SERVER_SOFTWARE WSGI环境变量,还可以在HTTP响应中设置adefault Server:标头。对于不是HTTP原始服务器的处理程序(例如BaseCGIHandlerCGIHandler),它被忽略.

在版本3.3中更改:术语“Python”是替换为实现特定术语,如“CPython”,“Jython”等.

get_scheme ()

返回用于当前请求的URL方案。defaultimplementation使用来自guess_scheme()wsgiref.util函数来猜测该方案应该是“http”还是“https”,基于当前请求的environ变量

setup_environ// ()

environ属性设置为完全填充的WSGI环境。默认实现使用上述所有方法和属性,以及get_stdin(), get_stderr()add_cgi_vars()方法以及wsgi_file_wrapper属性。它还插入一个SERVER_SOFTWARE keyif不存在,只要origin_server属性是一个真值并设置server_software属性.

Methods和attributes for自定义异常处理:

log_exceptionexc_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 3333 ).

默认实现只使用error_status,error_headerserror_body属性来生成输出页面。子类可以覆盖它以产生更多动态错误输出.

但请注意,从安全角度来看,不建议将outdiagnostics吐出到任何旧用户;理想情况下,你应该做一些特殊的toenable诊断输出,这就是为什么默认实现不包括任何.

error_status

用于错误响应的HTTP状态。这应该是PEP 3333 ;它默认为500个代码和消息.

error_headers

用于错误响应的HTTP标头。这应该是一个WSGIresponse标题列表((name, value)元组),如 PEP 3333 中所述。默认列表只是将内容类型设置为text/plain.

error_body

错误响应正文。这应该是HTTP响应主体字节串。它默认为纯文本,“发生了服务器错误。请联系管理员。“

PEP 3333 的“可选平台专用FileHandling”功能:

wsgi_file_wrapper

一个 wsgi.file_wrapper工厂,或None。thisattribute的默认值是​​wsgiref.util.FileWrapper类。

sendfile

覆盖以实现特定于平台的文件传输。仅当应用程序的返回值是wsgi_file_wrapper属性。如果它能够成功传输文件,它应返回truevalue,以便不执行defaulttransmission代码。thismethod的默认实现只返回false值.

其他方法和属性:

origin_server

如果使用处理程序的_write()_flush()直接与客户端通信,而不是通过CGI,则应将此属性设置为true值想要在一个特殊的Status: header.

这个属性的默认值在BaseHandler中为true,但在BaseCGIHandler中为false,这样的网关协议CGIHandler.

http_version

如果origin_server为true,则此字符串属性用于设置客户端响应集的HTTPversion。它默认为"1.0".

wsgiref.handlers.read_environ

将CGI变量从os.environ转换为PEP 3333“字节在unicode”字符串中,返回一个新字典。CGIHandlerIISCGIHandler使用此功能代替直接使用os.environ在使用Python 3的所有平台和Web服务器上都不一定符合WSGI标准 – 特别是OS的实际环境是Unicode(即Windows),或者环境是字节的那些,但是Python用来解码它的系统编码是ISO-8859-1以外的任何东西(例如使用UTF-8的Unix系统).

如果你正在实现自己的基于CGI的处理程序,你可能想要使用这个例程而不是仅仅复制os.environdirectly的值

//新版本3.2.

例子

这是一个有效的“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; charset=utf-8")]  # HTTP Headers    start_response(status, headers)    # The returned object is going to be printed    return [b"Hello World"]with make_server("", 8000, hello_world_app) as httpd:    print("Serving on port 8000...")    # Serve until process is killed    httpd.serve_forever()

评论被关闭。