wsgiref
--- WSGI 工具和參考實(shí)現(xiàn)?
Web 服務(wù)器網(wǎng)關(guān)接口(WSGI)是 Web 服務(wù)器軟件和用 Python 編寫的 Web 應(yīng)用程序之間的標(biāo)準(zhǔn)接口。 具有標(biāo)準(zhǔn)接口能夠讓支持 WSGI 的應(yīng)用程序與多種不同的 Web 服務(wù)器配合使用。
只有 Web 服務(wù)器和編程框架的開(kāi)發(fā)者才需要了解 WSGI 設(shè)計(jì)的每個(gè)細(xì)節(jié)和邊界情況。 你不需要了解 WSGI 的每個(gè)細(xì)節(jié)而只需要安裝一個(gè) WSGI 應(yīng)用程序或編寫使用現(xiàn)有框架的 Web 應(yīng)用程序。
wsgiref
is a reference implementation of the WSGI specification that can
be used to add WSGI support to a web server or framework. It provides utilities
for manipulating WSGI environment variables and response headers, base classes
for implementing WSGI servers, a demo HTTP server that serves WSGI applications,
types for static type checking,
and a validation tool that checks WSGI servers and applications for conformance
to the WSGI specification (PEP 3333).
參看 wsgi.readthedocs.io 獲取有關(guān) WSGI 的更多信息,以及教程和其他資源的鏈接。
wsgiref.util
-- WSGI 環(huán)境工具?
This module provides a variety of utility functions for working with WSGI
environments. A WSGI environment is a dictionary containing HTTP request
variables as described in PEP 3333. All of the functions taking an environ
parameter expect a WSGI-compliant dictionary to be supplied; please see
PEP 3333 for a detailed specification and
WSGIEnvironment
for a type alias that can be used
in type annotations.
- wsgiref.util.guess_scheme(environ)?
返回對(duì)于
wsgi.url_scheme
應(yīng)為 "http" 還是 "https" 的猜測(cè),具體方式是在 environ 中檢查HTTPS
環(huán)境變量。 返回值是一個(gè)字符串。此函數(shù)適用于創(chuàng)建一個(gè)包裝了 CGI 或 CGI 類協(xié)議例如 FastCGI 的網(wǎng)關(guān)。 通常,提供這種協(xié)議的服務(wù)器將包括一個(gè)
HTTPS
變量并會(huì)在通過(guò) SSL 接收請(qǐng)求時(shí)將其值設(shè)為 "1", "yes" 或 "on"。 這樣,此函數(shù)會(huì)在找到上述值時(shí)返回 "https",否則返回 "http"。
- wsgiref.util.request_uri(environ, include_query=True)?
使用 PEP 3333 的 "URL Reconstruction" 一節(jié)中的算法返回完整的請(qǐng)求 URL,可能包括查詢字符串。 如果 include_query 為假值,則結(jié)果 URI 中將不包括查詢字符串。
- wsgiref.util.application_uri(environ)?
類似于
request_uri()
,區(qū)別在于PATH_INFO
和QUERY_STRING
變量會(huì)被忽略。 結(jié)果為請(qǐng)求所指定的應(yīng)用程序?qū)ο蟮幕鶞?zhǔn) URI。
- wsgiref.util.shift_path_info(environ)?
將單個(gè)名稱從
PATH_INFO
變換為SCRIPT_NAME
并返回該名稱。 environ 目錄將被原地 修改;如果你需要保留原始PATH_INFO
或SCRIPT_NAME
不變請(qǐng)使用一個(gè)副本。如果
PATH_INFO
中沒(méi)有剩余的路徑節(jié),則返回None
。通常,此例程被用來(lái)處理請(qǐng)求 URI 路徑的每個(gè)部分,比如說(shuō)將路徑當(dāng)作是一系列字典鍵。 此例程會(huì)修改傳入的環(huán)境以使其適合發(fā)起調(diào)用位于目標(biāo) URI 上的其他 WSGI 應(yīng)用程序,如果有一個(gè) WSGI 應(yīng)用程序位于
/foo
,而請(qǐng)求 URI 路徑為/foo/bar/baz
,且位于/foo
的 WSGI 應(yīng)用程序調(diào)用了shift_path_info()
,它將獲得字符串 "bar",而環(huán)境將被更新以適合傳遞給位于/foo/bar
的 WSGI 應(yīng)用程序。 也就是說(shuō),SCRIPT_NAME
將由/foo
變?yōu)?/foo/bar
,而PATH_INFO
將由/bar/baz
變?yōu)?/baz
。當(dāng)
PATH_INFO
只是 "/" 時(shí),此例程會(huì)返回一個(gè)空字符串并在SCRIPT_NAME
末尾添加一個(gè)斜杠,雖然空的路徑節(jié)通常會(huì)被忽略,并且SCRIPT_NAME
通常也不以斜杠作為結(jié)束。 此行為是有意為之的,用來(lái)確保應(yīng)用程序在使用此例程執(zhí)行對(duì)象遍歷時(shí)能區(qū)分以/x
結(jié)束的和以/x/
結(jié)束的 URI。
- wsgiref.util.setup_testing_defaults(environ)?
以簡(jiǎn)短的默認(rèn)值更新 environ 用于測(cè)試目的。
此例程會(huì)添加 WSGI 所需要的各種參數(shù),包括
HTTP_HOST
,SERVER_NAME
,SERVER_PORT
,REQUEST_METHOD
,SCRIPT_NAME
,PATH_INFO
以及 PEP 3333 中定義的所有wsgi.*
變量。 它只提供默認(rèn)值,而不會(huì)替換這些變量的現(xiàn)有設(shè)置。此例程的目的是讓 WSGI 服務(wù)器的單元測(cè)試以及應(yīng)用程序設(shè)置測(cè)試環(huán)境更為容易。 它不應(yīng)該被實(shí)際的 WSGI 服務(wù)器或應(yīng)用程序所使用,因?yàn)樗玫氖羌贁?shù)據(jù)!
用法示例:
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 with make_server('', 8000, simple_app) as httpd: print("Serving on port 8000...") httpd.serve_forever()
除了上述的環(huán)境函數(shù),wsgiref.util
模塊還提供了以下輔助工具:
- wsgiref.util.is_hop_by_hop(header_name)?
如果 'header_name' 是 RFC 2616 所定義的 HTTP/1.1 "Hop-by-Hop" 標(biāo)頭則返回
True
。
- class wsgiref.util.FileWrapper(filelike, blksize=8192)?
A concrete implementation of the
wsgiref.types.FileWrapper
protocol used to convert a file-like object to an iterator. The resulting objects are iterables. As the object is iterated over, the optional blksize parameter will be repeatedly passed to the filelike object'sread()
method to obtain bytestrings to yield. Whenread()
returns an empty bytestring, iteration is ended and is not resumable.如果 filelike 具有
close()
方法,返回的對(duì)象也將具有close()
方法,并且它將在被調(diào)用時(shí)發(fā)起調(diào)用 filelike 對(duì)象的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)
在 3.11 版更改: Support for
__getitem__()
method has been removed.
wsgiref.headers
-- WSGI 響應(yīng)標(biāo)頭工具?
此模塊提供了一個(gè)單獨(dú)的類 Headers
,可以方便地使用一個(gè)映射類接口操作 WSGI 響應(yīng)標(biāo)頭。
- class wsgiref.headers.Headers([headers])?
創(chuàng)建一個(gè)包裝了 headers 的映射類對(duì)象,它必須為如 PEP 3333 所描述的由標(biāo)頭名稱/值元組構(gòu)成的列表。 headers 的默認(rèn)值為一個(gè)空列表。
Headers
對(duì)象支持典型的映射操作包括__getitem__()
,get()
,__setitem__()
,setdefault()
,__delitem__()
和__contains__()
。 對(duì)于以上各個(gè)方法,映射的鍵是標(biāo)頭名稱(大小寫不敏感),而值是關(guān)聯(lián)到該標(biāo)頭名稱的第一個(gè)值。 設(shè)置一個(gè)標(biāo)頭會(huì)移除該標(biāo)頭的任何現(xiàn)有值,再將一個(gè)新值添加到所包裝的標(biāo)頭列表末尾。 標(biāo)頭的現(xiàn)有順序通常會(huì)保持不變,只在所包裝的列表末尾添加新的標(biāo)頭。與字典不同,當(dāng)你試圖獲取或刪除所包裝的標(biāo)頭列表中不存在的鍵時(shí)
Headers
對(duì)象不會(huì)引發(fā)錯(cuò)誤。 獲取一個(gè)不存在的標(biāo)頭只是返回None
,而刪除一個(gè)不存在的標(biāo)頭則沒(méi)有任何影響。Headers
對(duì)象還支持keys()
,values()
以及items()
方法。 如果存在具有多個(gè)值的鍵則keys()
和items()
所返回的列表可能包括多個(gè)相同的鍵。 對(duì)Headers
對(duì)象執(zhí)行len()
的結(jié)果與items()
的長(zhǎng)度相同,也與所包裝的標(biāo)頭列表的長(zhǎng)度相同。 實(shí)際上,items()
方法只是返回所包裝的標(biāo)頭列表的一個(gè)副本。在
Headers
對(duì)象上調(diào)用bytes()
將返回適用于作為 HTTP 響應(yīng)標(biāo)頭來(lái)傳輸?shù)囊迅袷交止?jié)串。 每個(gè)標(biāo)頭附帶以逗號(hào)加空格分隔的值放置在一行中。 每一行都以回車符加換行符結(jié)束,且該字節(jié)串會(huì)以一個(gè)空行作為結(jié)束。除了映射接口和格式化特性,
Headers
對(duì)象還具有下列方法用來(lái)查詢和添加多值標(biāo)頭,以及添加具有 MIME 參數(shù)的標(biāo)頭:- get_all(name)?
返回包含指定標(biāo)頭的所有值的列表。
返回的列表項(xiàng)將按它們?cè)谠紭?biāo)頭列表中的出現(xiàn)或被添加到實(shí)例中的順序排序,并可能包含重復(fù)項(xiàng)。 任何被刪除并重新插入的字段總是會(huì)被添加到標(biāo)頭列表末尾。 如果給定名稱的字段不存在,則返回一個(gè)空列表。
- add_header(name, value, **_params)?
添加一個(gè)(可能有多個(gè)值)標(biāo)頭,帶有通過(guò)關(guān)鍵字參數(shù)指明的可選的 MIME 參數(shù)。
name 是要添加的標(biāo)頭字段。 可以使用關(guān)鍵字參數(shù)來(lái)為標(biāo)頭字段設(shè)置 MIME 參數(shù)。 每個(gè)參數(shù)必須為字符串或
None
。 參數(shù)名中的下劃線會(huì)被轉(zhuǎn)換為連字符,因?yàn)檫B字符不可在 Python 標(biāo)識(shí)符中出現(xiàn),但許多 MIME 參數(shù)名都包括連字符。 如果參數(shù)值為字符串,它會(huì)以name="value"
的形式被添加到標(biāo)頭值參數(shù)中。 如果為None
,則只會(huì)添加參數(shù)名。 (這適用于沒(méi)有值的 MIME 參數(shù)。) 示例用法:h.add_header('content-disposition', 'attachment', filename='bud.gif')
以上代碼將添加一個(gè)這樣的標(biāo)頭:
Content-Disposition: attachment; filename="bud.gif"
在 3.5 版更改: headers 形參是可選的。
wsgiref.simple_server
-- 一個(gè)簡(jiǎn)單的 WSGI HTTP 服務(wù)器?
此模塊實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的 HTTP 服務(wù)器 (基于 http.server
) 來(lái)發(fā)布 WSGI 應(yīng)用程序。 每個(gè)服務(wù)器實(shí)例會(huì)在給定的主機(jī)名和端口號(hào)上發(fā)布一個(gè) WSGI 應(yīng)用程序。 如果你想在一個(gè)主機(jī)名和端口號(hào)上發(fā)布多個(gè)應(yīng)用程序,你應(yīng)當(dāng)創(chuàng)建一個(gè)通過(guò)解析 PATH_INFO
來(lái)選擇每個(gè)請(qǐng)求要發(fā)起調(diào)用哪個(gè)應(yīng)用程序的 WSGI 應(yīng)用程序。 (例如,使用 wsgiref.util
中的 shift_path_info()
函數(shù)。)
- wsgiref.simple_server.make_server(host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler)?
創(chuàng)建一個(gè)新的 WSGI 服務(wù)器并在 host 和 port 上進(jìn)行監(jiān)聽(tīng),接受對(duì) app 的連接。 返回值是所提供的 server_class 的實(shí)例,并將使用指定的 handler_class 來(lái)處理請(qǐng)求。 app 必須是一個(gè)如 PEP 3333 所定義的 WSGI 應(yīng)用程序?qū)ο蟆?/p>
用法示例:
from wsgiref.simple_server import make_server, demo_app with 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_app(environ, start_response)?
此函數(shù)是一個(gè)小巧但完整的 WSGI 應(yīng)用程序,它返回一個(gè)包含消息 "Hello world!" 以及 environ 形參中提供的鍵/值對(duì)的文本頁(yè)面。 它適用于驗(yàn)證 WSGI 服務(wù)器 (例如
wsgiref.simple_server
) 是否能夠正確地運(yùn)行一個(gè)簡(jiǎn)單的 WSGI 應(yīng)用程序。
- class wsgiref.simple_server.WSGIServer(server_address, RequestHandlerClass)?
創(chuàng)建一個(gè)
WSGIServer
實(shí)例。 server_address 應(yīng)當(dāng)是一個(gè)(host,port)
元組,而 RequestHandlerClass 應(yīng)當(dāng)是http.server.BaseHTTPRequestHandler
的子類,它將被用來(lái)處理請(qǐng)求。你通常不需要調(diào)用此構(gòu)造器,因?yàn)?
make_server()
函數(shù)能為你處理所有的細(xì)節(jié)。WSGIServer
是http.server.HTTPServer
的子類,因此它所有的方法 (例如serve_forever()
和handle_request()
) 都是可用的。WSGIServer
還提供了以下 WSGI 專屬的方法:- set_app(application)?
將可調(diào)用對(duì)象 application 設(shè)為將要接受請(qǐng)求的 WSGI 應(yīng)用程序。
- get_app()?
返回當(dāng)前設(shè)置的應(yīng)用程序可調(diào)用對(duì)象。
但是,你通常不需要使用這些附加的方法,因?yàn)?
set_app()
通常會(huì)由make_server()
來(lái)調(diào)用,而get_app()
主要是針對(duì)請(qǐng)求處理句柄實(shí)例的。
- class wsgiref.simple_server.WSGIRequestHandler(request, client_address, server)?
為給定的 request 創(chuàng)建一個(gè) HTTP 處理句柄 (例如套接字),client_address (一個(gè)
(host,port)
元組),以及 server (WSGIServer
實(shí)例)。你不需要直接創(chuàng)建該類的實(shí)例;它們會(huì)根據(jù)
WSGIServer
對(duì)象的需要自動(dòng)創(chuàng)建。 但是,你可以子類化該類并將其作為 handler_class 提供給make_server()
函數(shù)。 一些可能在子類中重載的相關(guān)方法:- get_environ()?
Return a
WSGIEnvironment
dictionary for a request. The default implementation copies the contents of theWSGIServer
object'sbase_environ
dictionary attribute and then adds various headers derived from the HTTP request. Each call to this method should return a new dictionary containing all of the relevant CGI environment variables as specified in PEP 3333.
- get_stderr()?
返回應(yīng)被用作
wsgi.errors
流的對(duì)象。 默認(rèn)實(shí)現(xiàn)將只返回sys.stderr
。
- handle()?
處理 HTTP 請(qǐng)求。 默認(rèn)的實(shí)現(xiàn)會(huì)使用
wsgiref.handlers
類創(chuàng)建一個(gè)處理句柄實(shí)例來(lái)實(shí)現(xiàn)實(shí)際的 WSGI 應(yīng)用程序接口。
wsgiref.validate
--- WSGI 一致性檢查器?
當(dāng)創(chuàng)建新的 WSGI 應(yīng)用程序?qū)ο蟆⒖蚣?、服?wù)器或中間件時(shí),使用 wsgiref.validate
來(lái)驗(yàn)證新代碼的一致性是很有用的。 此模塊提供了一個(gè)創(chuàng)建 WSGI 應(yīng)用程序?qū)ο蟮暮瘮?shù)來(lái)驗(yàn)證 WSGI 服務(wù)器或網(wǎng)關(guān)與 WSGI 應(yīng)用程序?qū)ο笾g的通信,以便檢查雙方的協(xié)議一致性。
請(qǐng)注意這個(gè)工具并不保證完全符合 PEP 3333;此模塊沒(méi)有報(bào)告錯(cuò)誤并不一定表示不存在錯(cuò)誤。 但是,如果此模塊確實(shí)報(bào)告了錯(cuò)誤,那么幾乎可以肯定服務(wù)器或應(yīng)用程序不是 100% 符合要求的。
此模塊是基于 Ian Bicking 的 "Python Paste" 庫(kù)的 paste.lint
模塊。
- wsgiref.validate.validator(application)?
包裝 application 并返回一個(gè)新的 WSGI 應(yīng)用程序?qū)ο蟆? 返回的應(yīng)用程序?qū)⑥D(zhuǎn)發(fā)所有請(qǐng)求到原始的 application,并將檢查 application 和發(fā)起調(diào)用它的服務(wù)器是否都符合 WSGI 規(guī)范和 RFC 2616。
任何被檢測(cè)到的不一致性都會(huì)導(dǎo)致引發(fā)
AssertionError
;但是請(qǐng)注意,如何對(duì)待這些錯(cuò)誤取決于具體服務(wù)器。 例如,wsgiref.simple_server
和其他基于wsgiref.handlers
的服務(wù)器(它們沒(méi)有重載錯(cuò)誤處理方法來(lái)做其他操作)將簡(jiǎn)單地輸出一條消息報(bào)告發(fā)生了錯(cuò)誤,并將回溯轉(zhuǎn)給sys.stderr
或者其他錯(cuò)誤數(shù)據(jù)流。這個(gè)包裝器也可能會(huì)使用
warnings
模塊生成輸出來(lái)指明存在問(wèn)題但實(shí)際上未被 PEP 3333 所禁止的行為。 除非它們被 Python 命令行選項(xiàng)或warnings
API 所屏蔽,否則任何此類警告都將被寫入到sys.stderr
(不是wsgi.errors
,除非它們恰好是同一個(gè)對(duì)象)。用法示例:
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 b"Hello World" # This is the application wrapped in a validator validator_app = validator(simple_app) with make_server('', 8000, validator_app) as httpd: print("Listening on port 8000....") httpd.serve_forever()
wsgiref.handlers
-- 服務(wù)器/網(wǎng)關(guān)基類?
此模塊提供了用于實(shí)現(xiàn) WSGI 服務(wù)器和網(wǎng)關(guān)的處理句柄基類。 這些基類可處理大部分與 WSGI 應(yīng)用程序通信的工作,只要給予它們一個(gè)帶有輸入、輸出和錯(cuò)誤流的 CGI 類環(huán)境。
- class wsgiref.handlers.CGIHandler?
通過(guò)
sys.stdin
,sys.stdout
,sys.stderr
和os.environ
發(fā)起基于 CGI 的調(diào)用。 這在當(dāng)你有一個(gè) WSGI 應(yīng)用程序并想將其作為 CGI 腳本運(yùn)行時(shí)很有用處。 只需發(fā)起調(diào)用CGIHandler().run(app)
,其中app
是你想要發(fā)起調(diào)用的 WSGI 應(yīng)用程序。該類是
BaseCGIHandler
的子類,它將設(shè)置wsgi.run_once
為真值,wsgi.multithread
為假值,wsgi.multiprocess
為真值,并總是使用sys
和os
來(lái)獲取所需的 CGI 流和環(huán)境。
- class wsgiref.handlers.IISCGIHandler?
CGIHandler
的一個(gè)專門化替代,用于在 Microsoft 的 IIS Web 服務(wù)器上部署,無(wú)需設(shè)置 config allowPathInfo 選項(xiàng) (IIS>=7) 或 metabase allowPathInfoForScriptMappings (IIS<7)。默認(rèn)情況下,IIS 給出的
PATH_INFO
會(huì)與前面的SCRIPT_NAME
重復(fù),導(dǎo)致想要實(shí)現(xiàn)路由的 WSGI 應(yīng)用程序出現(xiàn)問(wèn)題。 這個(gè)處理句柄會(huì)去除任何這樣的重復(fù)路徑。IIS 可被配置為傳遞正確的
PATH_INFO
,但這會(huì)導(dǎo)致另一個(gè)PATH_TRANSLATED
出錯(cuò)的問(wèn)題。 幸運(yùn)的是這個(gè)變量很少被使用并且不被 WSGI 所保證。 但是在 IIS<7 上,這個(gè)設(shè)置只能在 vhost 層級(jí)上進(jìn)行,影響到所有其他腳本映射,其中許多在受PATH_TRANSLATED
問(wèn)題影響時(shí)都會(huì)中斷運(yùn)行。 因此 IIS<7 的部署幾乎從不附帶這樣的修正(即使 IIS7 也很少使用它,因?yàn)樗匀徊粠?UI)。CGI 代碼沒(méi)有辦法確定該選項(xiàng)是否已設(shè)置,因此提供了一個(gè)單獨(dú)的處理句柄類。 它的用法與
CGIHandler
相同,即通過(guò)調(diào)用IISCGIHandler().run(app)
,其中app
是你想要發(fā)起調(diào)用的 WSGI 應(yīng)用程序。3.2 新版功能.
- class wsgiref.handlers.BaseCGIHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)?
類似于
CGIHandler
,但是改用sys
和os
模塊,CGI 環(huán)境和 I/O 流會(huì)被顯式地指定。 multithread 和 multiprocess 值被用來(lái)為處理句柄實(shí)例所運(yùn)行的任何應(yīng)用程序設(shè)置wsgi.multithread
和wsgi.multiprocess
旗標(biāo)。該類是
SimpleHandler
的子類,旨在用于 HTTP "原始服務(wù)器" 以外的軟件。 如果你在編寫一個(gè)網(wǎng)關(guān)協(xié)議實(shí)現(xiàn)(例如 CGI, FastCGI, SCGI 等等),它使用Status:
標(biāo)頭來(lái)發(fā)布 HTTP 狀態(tài),你可能會(huì)想要子類化該類而不是SimpleHandler
。
- class wsgiref.handlers.SimpleHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)?
類似于
BaseCGIHandler
,但被設(shè)計(jì)用于 HTTP 原始服務(wù)器。 如果你在編寫一個(gè) HTTP 服務(wù)器實(shí)現(xiàn),你可能會(huì)想要子類化該類而不是BaseCGIHandler
。該類是
BaseHandler
的子類。 它重載了__init__()
,get_stdin()
,get_stderr()
,add_cgi_vars()
,_write()
和_flush()
方法以支持通過(guò)構(gòu)造器顯式地設(shè)置環(huán)境和流。 所提供的環(huán)境和流存儲(chǔ)在stdin
,stdout
,stderr
和environ
屬性中。stdout 的
write()
方法應(yīng)該完整寫入每個(gè)數(shù)據(jù)塊,與io.BufferedIOBase
一樣。
- class wsgiref.handlers.BaseHandler?
這是適用于運(yùn)行 WSGI 應(yīng)用程序的抽象基類。 每個(gè)實(shí)例將處理一個(gè)單獨(dú)的 HTTP 請(qǐng)求,不過(guò)在原則上你也可以創(chuàng)建一個(gè)可針對(duì)多個(gè)請(qǐng)求重用的子類。
BaseHandler
實(shí)例只有一個(gè)方法提供給外部使用:- run(app)?
運(yùn)行指定的 WSGI 應(yīng)用程序 app。
所有的
BaseHandler
其他方法都是在運(yùn)行應(yīng)用程序過(guò)程中由該方法發(fā)起調(diào)用的,因此主要是為了允許定制運(yùn)行過(guò)程。以下方法必須在子類中被重載:
- _write(data)?
緩沖字節(jié)數(shù)據(jù) data 以便傳輸給客戶端。 如果此方法真的傳輸了數(shù)據(jù)也是可以的;
BaseHandler
只有在底層系統(tǒng)真有這樣的區(qū)分時(shí)才會(huì)區(qū)分寫入和刷新操作以提高效率。
- _flush()?
強(qiáng)制將緩沖的數(shù)據(jù)傳輸給客戶端。 如果此方法無(wú)任何操作也是可以的(例如,
_write()
實(shí)際上已發(fā)送了數(shù)據(jù))。
- get_stdin()?
Return an object compatible with
InputStream
suitable for use as thewsgi.input
of the request currently being processed.
- get_stderr()?
Return an object compatible with
ErrorStream
suitable for use as thewsgi.errors
of the request currently being processed.
- add_cgi_vars()?
將當(dāng)前請(qǐng)求的 CGI 變量插入到
environ
屬性。
以下是一些你可能會(huì)想要重載的其他方法。 但這只是個(gè)簡(jiǎn)略的列表,它不包括每個(gè)可被重載的方法。 你應(yīng)當(dāng)在在嘗試創(chuàng)建自定義的
BaseHandler
子類之前參閱文檔字符串和源代碼來(lái)了解更多信息。用于自定義 WSGI 環(huán)境的屬性和方法:
- wsgi_multithread?
用于
wsgi.multithread
環(huán)境變量的值。 它在BaseHandler
中默認(rèn)為真值,但在其他子類中可能有不同的默認(rèn)值(或是由構(gòu)造器來(lái)設(shè)置)。
- wsgi_multiprocess?
用于
wsgi.multiprocess
環(huán)境變量的值。 它在BaseHandler
中默認(rèn)為真值,但在其他子類中可能有不同的默認(rèn)值(或是由構(gòu)造器來(lái)設(shè)置)。
- wsgi_run_once?
用于
wsgi.run_once
環(huán)境變量的值。 它在BaseHandler
中默認(rèn)為假值,但在CGIHandler
中默認(rèn)為真值。
- os_environ?
要包括在每個(gè)請(qǐng)求的 WSGI 環(huán)境中的默認(rèn)環(huán)境變量。 在默認(rèn)情況下,這是當(dāng)
wsgiref.handlers
被導(dǎo)入時(shí)的os.environ
的一個(gè)副本,但也可以在類或?qū)嵗龑蛹?jí)上創(chuàng)建它們自己的子類。 請(qǐng)注意該字典應(yīng)當(dāng)被當(dāng)作是只讀的,因?yàn)槟J(rèn)值會(huì)在多個(gè)類和實(shí)際之間共享。
- server_software?
如果設(shè)置了
origin_server
屬性,該屬性的值會(huì)被用來(lái)設(shè)置默認(rèn)的SERVER_SOFTWARE
WSGI 環(huán)境變量,并且還會(huì)被用來(lái)設(shè)置 HTTP 響應(yīng)中默認(rèn)的Server:
標(biāo)頭。 它會(huì)被不是 HTTP 原始服務(wù)器的處理句柄所忽略 (例如BaseCGIHandler
和CGIHandler
)。在 3.3 版更改: 名稱 "Python" 會(huì)被替換為實(shí)現(xiàn)專屬的名稱如 "CPython", "Jython" 等等。
- get_scheme()?
返回當(dāng)前請(qǐng)求所使用的 URL 方案。 默認(rèn)的實(shí)現(xiàn)會(huì)使用來(lái)自
wsgiref.util
的guess_scheme()
函數(shù)根據(jù)當(dāng)前請(qǐng)求的environ
變量來(lái)猜測(cè)方案應(yīng)該是 "http" 還是 "https"。
- setup_environ()?
將
environ
屬性設(shè)為填充了完整內(nèi)容的 WSGI 環(huán)境。 默認(rèn)的實(shí)現(xiàn)會(huì)使用上述的所有方法和屬性,加上get_stdin()
,get_stderr()
和add_cgi_vars()
方法以及wsgi_file_wrapper
屬性。 它還會(huì)插入一個(gè)SERVER_SOFTWARE
鍵,如果該鍵還不存在的話,只要origin_server
屬性為真值并且設(shè)置了server_software
屬性。
用于自定義異常處理的方法和屬性:
- log_exception(exc_info)?
將 exc_info 元素記錄到服務(wù)器日志。 exc_info 是一個(gè)
(type, value, traceback)
元組。 默認(rèn)的實(shí)現(xiàn)會(huì)簡(jiǎn)單地將回溯信息寫入請(qǐng)求的wsgi.errors
流并刷新它。 子類可以重載此方法來(lái)修改格式或重設(shè)輸出目標(biāo),通過(guò)郵件將回溯信息發(fā)給管理員,或執(zhí)行任何其他符合要求的動(dòng)作。
- traceback_limit?
要包括在默認(rèn)
log_exception()
方法的回溯信息輸出中的最大幀數(shù)。 如果為None
,則會(huì)包括所有的幀。
- error_output(environ, start_response)?
此方法是一個(gè)為用戶生成錯(cuò)誤頁(yè)面的 WSGI 應(yīng)用程序。 它僅當(dāng)將標(biāo)頭發(fā)送給客戶端之前發(fā)生錯(cuò)誤時(shí)會(huì)被發(fā)起調(diào)用。
此方法可使用
sys.exc_info()
來(lái)訪問(wèn)當(dāng)前錯(cuò)誤信息,并應(yīng)當(dāng)在調(diào)用 start_response 時(shí)將該信息傳遞給它(如 PEP 3333 的 "Error Handling" 部分所描述的)。默認(rèn)的實(shí)現(xiàn)只是使用
error_status
,error_headers
, 和error_body
屬性來(lái)生成一個(gè)輸出頁(yè)面。 子類可以重載此方法來(lái)產(chǎn)生更動(dòng)態(tài)化的錯(cuò)誤輸出。但是請(qǐng)注意,從安全角度看來(lái)是不建議將診斷信息暴露給任何用戶的;理想的做法是你應(yīng)當(dāng)通過(guò)特別處理來(lái)啟用診斷輸出,因此默認(rèn)的實(shí)現(xiàn)并不包括這樣的內(nèi)容。
- error_status?
用于錯(cuò)誤響應(yīng)的 HTTP 狀態(tài)。 這應(yīng)當(dāng)是一個(gè)在 PEP 3333 中定義的字符串;它默認(rèn)為代碼 500 以相應(yīng)的消息。
- error_headers?
用于錯(cuò)誤響應(yīng)的 HTTP 標(biāo)頭。 這應(yīng)當(dāng)是由 WSGI 響應(yīng)標(biāo)頭 (
(name, value)
元組) 構(gòu)成的列表,如 PEP 3333 所定義的。 默認(rèn)的列表只是將內(nèi)容類型設(shè)為text/plain
。
- error_body?
錯(cuò)誤響應(yīng)體。 這應(yīng)當(dāng)是一個(gè) HTTP 響應(yīng)體字節(jié)串。 它默認(rèn)為純文本 "A server error occurred. Please contact the administrator."
用于 PEP 3333 的 "可選的平臺(tái)專屬文件處理" 特性的方法和屬性:
- wsgi_file_wrapper?
A
wsgi.file_wrapper
factory, compatible withwsgiref.types.FileWrapper
, orNone
. The default value of this attribute is thewsgiref.util.FileWrapper
class.
- sendfile()?
重載以實(shí)現(xiàn)平臺(tái)專屬的文件傳輸。 此方法僅在應(yīng)用程序的返回值是由
wsgi_file_wrapper
屬性指定的類的實(shí)例時(shí)會(huì)被調(diào)用。 如果它能夠成功地傳輸文件則應(yīng)當(dāng)返回真值,以使得默認(rèn)的傳輸代碼將不會(huì)被執(zhí)行。 此方法的默認(rèn)實(shí)現(xiàn)只會(huì)返回假值。
雜項(xiàng)方法和屬性:
- origin_server?
該屬性在處理句柄的
_write()
和_flush()
被用于同客戶端直接通信而不是通過(guò)需要 HTTP 狀態(tài)為某種特殊Status:
標(biāo)頭的 CGI 類網(wǎng)關(guān)協(xié)議時(shí)應(yīng)當(dāng)被設(shè)為真值該屬性在
BaseHandler
中默認(rèn)為真值,但在BaseCGIHandler
和CGIHandler
中則為假值。
- http_version?
如果
origin_server
為真值,則該字符串屬性會(huì)被用來(lái)設(shè)置給客戶端的響應(yīng)的 HTTP 版本。 它的默認(rèn)值為"1.0"
。
- wsgiref.handlers.read_environ()?
將來(lái)自
os.environ
的 CGI 變量轉(zhuǎn)碼為 PEP 3333 "bytes in unicode" 字符串,返回一個(gè)新的字典。 此函數(shù)被CGIHandler
和IISCGIHandler
用來(lái)替代直接使用os.environ
,后者不一定在所有使用 Python 3 的平臺(tái)和 Web 服務(wù)器上都符合 WSGI 標(biāo)準(zhǔn) -- 特別是當(dāng) OS 的實(shí)際環(huán)境為 Unicode 時(shí) (例如 Windows),或者當(dāng)環(huán)境為字節(jié)數(shù)據(jù),但被 Python 用來(lái)解碼它的系統(tǒng)編碼格式不是 ISO-8859-1 時(shí) (例如使用 UTF-8 的 Unix 系統(tǒng))。如果你要實(shí)現(xiàn)自己的基于 CGI 的處理句柄,你可能會(huì)想要使用此例程而不是簡(jiǎn)單地從
os.environ
直接拷貝值。3.2 新版功能.
wsgiref.types
-- WSGI types for static type checking?
This module provides various types for static type checking as described in PEP 3333.
3.11 新版功能.
- class wsgiref.types.StartResponse?
A
typing.Protocol
describing start_response() callables (PEP 3333).
- wsgiref.types.WSGIEnvironment?
A type alias describing a WSGI environment dictionary.
- wsgiref.types.WSGIApplication?
A type alias describing a WSGI application callable.
- class wsgiref.types.InputStream?
A
typing.Protocol
describing a WSGI Input Stream.
- class wsgiref.types.ErrorStream?
A
typing.Protocol
describing a WSGI Error Stream.
- class wsgiref.types.FileWrapper?
A
typing.Protocol
describing a file wrapper. Seewsgiref.util.FileWrapper
for a concrete implementation of this protocol.
例子?
這是一個(gè)可運(yùn)行的 "Hello World" WSGI 應(yīng)用程序:
"""
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.
"""
from wsgiref.simple_server import make_server
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()
Example of a WSGI application serving the current directory, accept optional directory and port number (default: 8000) on the command line:
"""
Small wsgiref based web server. Takes a path to serve from and an
optional port number (defaults to 8000), then tries to serve files.
MIME types are guessed from the file names, 404 errors are raised
if the file is not found.
"""
import mimetypes
import os
import sys
from wsgiref import simple_server, util
def app(environ, respond):
# Get the file name and MIME type
fn = os.path.join(path, environ["PATH_INFO"][1:])
if "." not in fn.split(os.path.sep)[-1]:
fn = os.path.join(fn, "index.html")
mime_type = mimetypes.guess_type(fn)[0]
# Return 200 OK if file exists, otherwise 404 Not Found
if os.path.exists(fn):
respond("200 OK", [("Content-Type", mime_type)])
return util.FileWrapper(open(fn, "rb"))
else:
respond("404 Not Found", [("Content-Type", "text/plain")])
return [b"not found"]
if __name__ == "__main__":
# Get the path and port from command-line arguments
path = sys.argv[1] if len(sys.argv) > 1 else os.getcwd()
port = int(sys.argv[2]) if len(sys.argv) > 2 else 8000
# Make and start the server until control-c
httpd = simple_server.make_server("", port, app)
print(f"Serving {path} on port {port}, control-C to stop")
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("Shutting down.")
httpd.server_close()