wsgiref --- WSGI 工具與參考實作

原始碼:Lib/wsgiref


網頁伺服器閘道介面 (WSGI) 是一個標準介面,用於連接網頁伺服器軟體與使用 Python 撰寫的網頁應用程式,擁有一個標準介面使得支援 WSGI 的應用程式可以與多個不同的網頁伺服器運行。

只有網頁伺服器與程式框架的作者需要瞭解 WSGI 設計的每個細節與邊角案例,你並不需要為了安裝 WSGI 應用程式或是使用現有框架撰寫網頁應用程式而必須理解每個細節。

wsgiref 是 WSGI 規格的參考實作,可用於新增 WSGI 來支援網頁伺服器或框架,它提供操作 WSGI 環境變數以及回應標頭的工具,用於實作 WSGI 伺服器的基本類別,提供用於示範 HTTP 伺服器的 WSGI 應用程式、靜態型別檢查、以及驗證 WSGI 伺服器與應用程式是否符合 WSGI 規格的驗證工具 (PEP 3333)。

參閱wsgi.readthedocs.io 更多 WSGI 相關資訊,以及教學連結與其他資源。

wsgiref.util -- WSGI 環境工具

這個模組提供許多用於處理 WSGI 環境運作的功能。WSGI 環境是一個包含 HTTP 請求變數的字典,如PEP 3333 所述。所有接受environ 的參數的函式都需要提供符合 WSGI 標準的字典;請參閱PEP 3333 取得詳細規格,以及WSGIEnvironment 取得可用於使用型別註釋的型別別名。

wsgiref.util.guess_scheme(environ)

透過檢查environ 字典中的HTTPS 環境變數,回傳wsgi.url_scheme 應該是 "http" 或 "https" 的猜測。回傳值為一個字串。

當建立一個包裝 CGI 或類似 FastCGI 的 CGI-like 協議閘道時,此函式非常有用。例如 FastCGI,通常提供這類協議的伺服器在通過 SSL 接收到請求時會包含 "1","yes",或 "on" 的HTTPS 變數,因此,如果找到這樣的值,此函式回傳 "https",否則回傳 "http"。

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

根據PEP 3333 中 "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 字典會在適當時機被modified;如果你需要保留原始完好無損的PATH_INFOSCRIPT_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 和結尾為/x/ 的 URIs。

wsgiref.util.setup_testing_defaults(environ)

為測試目的,以簡單的預設值更新environ

這個程式新增 WSGI 所需的各種參數,包括HTTP_HOSTSERVER_NAMESERVER_PORTREQUEST_METHODSCRIPT_NAMEPATH_INFO,以及所有PEP 3333 定義的wsgi.* 變數,它只提供預設值,並且不會取代現有的這些變數設定。

這個程式目的為了讓 WSGI 伺服器和應用程式的單元測試更容易建置虛擬環境。實際的 WSGI 伺服器或應用程式不應該使用它,因為所產生的數據是假的!

Example usage (see alsodemo_app()for another example):

fromwsgiref.utilimportsetup_testing_defaultsfromwsgiref.simple_serverimportmake_server# A relatively simple WSGI application. It's going to print out the# environment dictionary after being updated by setup_testing_defaultsdefsimple_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")forkey,valueinenviron.items()]returnretwithmake_server('',8000,simple_app)ashttpd: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 "Hop-by-Hop" 標頭,則回傳True

classwsgiref.util.FileWrapper(filelike,blksize=8192)

wsgiref.types.FileWrapper 協議的具體實作,用於將類檔案物件轉換為iterator。產生的物件是iterable。當物件進行疊代時,將可選的blksize 引數重複傳遞給filelike 物件的read() 方法來獲得將產生(yield)的位元組字串。當read() 回傳一個空位元組字串,代表疊代已結束且無法回復。

如果filelikeclose() 方法,則回傳的物件也會具有close() 方法,並在呼叫時叫用filelike 物件的close() 方法。

用法範例:

fromioimportStringIOfromwsgiref.utilimportFileWrapper# 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)forchunkinwrapper:print(chunk)

在 3.11 版的變更:已移除對__getitem__() 方法的支援。

wsgiref.headers -- WSGI 回應標頭工具

這個模組提供單一類別Headers,用於使用類似對映的介面方便地操作 WSGI 回應標頭。

classwsgiref.headers.Headers([headers])

建立一個類似對映物件並包裝headers,並且必須是符合PEP 3333 描述的 name/value 元組的標頭串列。headers 的預設值是一個空串列。

Headers 物件支援典型對映操作包括__getitem__()get()__setitem__()setdefault()__delitem__() 以及__contains__()。對於這些方法中的每一個,鍵是標頭名稱(以不區分大小寫方式處理),而值則是與該標頭名稱關聯的第一個值。設定標頭會刪除該標頭的所有現有值,然後將新值添加到包裝的標頭串列末尾。標頭的現有順序通常保持不變,新標頭會添加到包裝串列的末尾。

不同於字典,當你嘗試取得或刪除包裝的標頭串列不存在的鍵,Headers 物件不會引發例外錯誤。取得不存在的標頭只會回傳None,而刪除不存在的標頭則不會有任何效果。

Headers 物件還支援keys()value()、和items() 方法。由keys()items() 回傳的串列在存在多值標頭時可能會包含相同的鍵。Headers 物件的len()items() 的長度相同,也與包裝標頭串列的長度相同。實際上,items() 方法只是回傳包裝的標頭串列的副本。

Header 物件呼叫bytes() 會回傳適合作為 HTTP 傳輸回應標頭的格式化的位元組字串。每個標頭都與其值一起置於一行上,由冒號與空格分隔。每行以回車(carriage return)和換行(line feed)結束,而該位元組字串則以空行結束。

除了對映介面和格式化功能外,Headers 物件還具有以下查詢及附加多值標頭的以及附加 MIME 參數標頭的方法:

get_all(name)

回傳指定標頭的所有值的串列。

回傳的串列按照它們在在原始的標頭串列出現的順序或是被添加到此實例的順序進行排序,並且可能包含重複的內容。任何被刪除並重新插入的欄位都會被添加到標頭串列的末尾。如果不存在指定名稱的欄位,則回傳空串列。

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 應用程式。如果你想要在單一主機與埠上提供多個應用程式,你應該建立一個 WSGI 應用程式以剖析PATH_INFO 去選擇為每個請求叫用哪個應用程式。(例如,使用來自wsgiref.utilshift_path_info() 函式。)

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

建立一個新的 WSGI 伺服器監聽hostport,接受app 的連線。回傳值是提供server_class 的實例,並將使用指定的handler_class 處理請求。app 必須是一個 WSGI 應用程式物件,如PEP 3333 所定義。

用法範例:

fromwsgiref.simple_serverimportmake_server,demo_appwithmake_server('',8000,demo_app)ashttpd:print("Serving HTTP on port 8000...")# Respond to requests until process is killedhttpd.serve_forever()# Alternative: serve one request, then exithttpd.handle_request()
wsgiref.simple_server.demo_app(environ,start_response)

這個函式是一個簡單但完整的 WSGI 應用程式,它回傳一個包含訊息 "Hello world!" 和在environ 參數中提供的鍵值對串列的文字頁面。這對於驗證 WSGI 伺服器(例如wsgiref.simple_server)是否能正確執行簡單的 WSGI 應用程式非常有用。

Thestart_response callable should follow theStartResponse protocol.

classwsgiref.simple_server.WSGIServer(server_address,RequestHandlerClass)

建立一個WSGIServer 實例。server_address 應該是一個(host,port) 元組,而RequestHandlerClass 應該是http.server.BaseHTTPRequestHandler 的子類別,將用於處理請求。

通常你不需要呼叫這個建構函式(constructor),因為make_server() 函式可以為你處理所有細節。

WSGIServerhttp.server.HTTPServer 的子類別,因此它的所有方法(例如serve_forever()handle_request())都可用。WSGIServer 也提供這些特定於 WSGI 的方法:

set_app(application)

將可呼叫的application 設定為接收請求的 WSGI 應用程式。

get_app()

回傳目前設定應用程式的可呼叫物件。

然而,通常情況下你不需要去使用這些額外方法,因為set_app() 通常會被make_server() 呼叫而get_app() 主要存在於請求處理程式(handler)實例的好處上。

classwsgiref.simple_server.WSGIRequestHandler(request,client_address,server)

為給定的request*(即一個 socket)、*client_address*(一個 ``(host,port)`` 位元組)、*server (WSGIServer 實例) 建立一個 HTTP 處理程式(handler)。

你不需要直接建立這個類別的實例;它們會在需要時由WSGIServer 物件自動建立。不過,你可以建立這個類別的子類別並將其作為handler_class 提供給make_server() 函式。一些可能相關的方法可以在子類別中進行覆寫:

get_environ()

唯一個請求回傳一個WSGIEnvironment 字典。預設的實作會複製WSGIServer 物件的base_environ 字典屬性的內容以及添加從 HTTP 請求中衍生的各種標頭。每次呼叫這個方法都應該回傳一個包含所有如PEP 3333 所指定的相關 CGI 環境變數的新字典。

get_stderr()

回傳的物件應該被用作wsgi.errors 串流。預設實作只會回傳sys.stderr

handle()

處理 HTTP 請求。預設實作會使用wsgiref.handler 類別來建立處置程式(handler)實例來實作實際 WSGI 應用程式介面。

wsgiref.validate --- WSGI 符合性檢查

當建立新的 WSGI 應用程式物件、框架、伺服器、或是中介軟體(middleware)時,使用wsgiref.validate 來驗證新程式碼的符合性可能會很有用。這個模組提供一個函式用於建立 WSGI 應用程式物件,並用於驗證 WSGI 伺服器或是閘道與 WSGI 應用程式物件之間的通訊,以檢查雙方協議的符合性。

請注意這個工具並不保證完全符合PEP 3333;這個模組中的錯誤不一定代表不存在錯誤。但是,如果如果這個模組產生錯誤,那麼幾乎可以確定伺服器或應用程式不是 100% 符合標準。

這個模組基於 Ian Bicking 的 "Python Paste" 函式庫的paste.lint 模組。

wsgiref.validate.validator(application)

包裝application 並回傳一個新的 WSGI 應用程式物件。回傳的應用程式將轉發所有請求給原始的application,並檢查application 和呼叫它的伺服器是否符合 WSGI 規範和RFC 2616

任何在AssertionError 中偵測不符合結果都會發起例外;但請注意,如何處理這些錯誤取決於伺服器。例如,基於wsgiref.handlerswsgiref.simple_server 以及其他伺服器(未覆蓋錯誤處理方法以執行其他操作的伺服器)將僅輸出一條錯誤訊息,指示發生錯誤,並將回溯訊息輸出到sys.stderr 或是其他錯誤串流。

這個包裝器也可以使用warnings 模組生成輸出去指示一些可能有疑慮但實際上可能不會被PEP 3333 禁止的行為。除非使用 Python 命令列選項或warnings API,抑制了這些警告,否則這類警告將被寫入到sys.stderrnotwsgi.errors,除非它們碰巧是相同的物件)。

用法範例:

fromwsgiref.validateimportvalidatorfromwsgiref.simple_serverimportmake_server# Our callable object which is intentionally not compliant to the# standard, so the validator is going to breakdefsimple_app(environ,start_response):status='200 OK'# HTTP Statusheaders=[('Content-type','text/plain')]# HTTP Headersstart_response(status,headers)# This is going to break because we need to return a list, and# the validator is going to inform usreturnb"Hello World"# This is the application wrapped in a validatorvalidator_app=validator(simple_app)withmake_server('',8000,validator_app)ashttpd:print("Listening on port 8000....")httpd.serve_forever()

wsgiref.handlers -- 伺服器 / 閘道基本類別

這個模組提供實作 WSGI 伺服器和閘道的基礎處理程式(handler)類別。這些基底類別處理程式大部分與 WSGI 應用程式通訊的工作,只要它們被提供 CGI-like 環境,以及輸入、輸出和錯誤串流。

classwsgiref.handlers.CGIHandler

這是基於 CGI 的呼叫方式並透過sys.stdinsys.stdoutsys.stderros.environ。當你擁有一個 WSGI 應用程式並希望將其作為 CGI 腳本運行時是很有用的。只需叫用CGIHandler().run(app),其中app 是你希望叫用的 WSGI 應用程式物件。

這個類別是BaseCGIHandler 的子類別將wsgi.run_once 設置為 true,wsgi.multithread 設置為 false,並將wsgi.multiprocess 設置為 true,並且始終使用sysos 來取得所需的 CGI 串流以及環境。

classwsgiref.handlers.IISCGIHandler

這是用於在 Microsoft 的 IIS 網頁伺服器上部署時使用的CGIHandler 的一個專門替代選擇,無需設置 config 的 allowPathInfo 選項(IIS>=7),或 metabase 的 allowPathInfoForScriptMappings 選項(IIS<7)。

預設情況下,IIS 提供的PATH_INFO 會在前面複製SCRIPT_NAME,對於希望實作路由的 WSGI 應用程式造成問題。這個處理程式(handler)會移除任何這樣的重複路徑。

IIS 可以配置去傳遞正確的PATH_INFO,但這會導致PATH_TRANSLATED 是錯誤的問題。幸運的是這個變數很少被使用並且不受 WSGI 保證。然而,在 IIS<7 上,這個設置只能在虛擬主機層級進行,影響所有其他腳本的對映,其中許多在暴露PATH_TRANSLATED 問題時會中斷。由於這個原因幾乎從不會使用修復的 IIS<7(即使是 IIS7 也很少使用它,因為它仍然沒有相應的 UI)。

CGI 程式碼無法知道是否已設置該選項,因此提供了一個獨立的處理程式(handler)類別。它的使用方式與CGIHandler 相同,即透過呼叫IISCGIHandler().run(app) 來使用,其中app 是你希望叫用的 WSGI 應用程式物件。

在 3.2 版被加入.

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

類似於CGIHandler,但不是使用sysos 模組,而是明確指定 CGI 環境與 I/O 串流。multithreadmultiprocess 值用於設置由處理程式(handler)實例運行的任何應用程式的旗標。

這個類別是專門為除了 HTTP "origin servers" 以外的軟體一起使用的SimpleHandler 的子類別。如果你正在撰寫一個使用Status: 標頭來發送 HTTP 狀態的閘道協議實作(例如 CGI、FastCGI、SCGI 等),你可能會想要子類化這個類別來替代SimpleHandler

classwsgiref.handlers.SimpleHandler(stdin,stdout,stderr,environ,multithread=True,multiprocess=False)

類似於BaseCGIHandler,但是被設計使用在 HTTP origin 伺服器。如果你正在撰寫 HTTP 伺服器的實作,你可能會想要子類別化這個類別來替代BaseCGIHandler

這個類別是BaseHandler 的子類別。它透過建構函式去覆寫__init__()get_stdin()get_stderr()add_cgi_vars()_write()、和_flush() 方法來明確提供設置環境與串流。提供的環境與串流被儲存在stdinstdoutstderr、和environ 環境中。

stdoutwrite() 方法應該完整地寫入每個塊(chunk),像是io.BufferedIOBase

classwsgiref.handlers.BaseHandler

這是一個運行 WSGI 應用程式的抽象基底類別。每個實例將處理單個 HTTP 請求,儘管原則上你可以建立一個可重用於多個請求的子類別。

BaseHandler 實例只有一個供外部使用的方法:

run(app)

運行指定 WSGI 應用程式,app

此方法在運行應用程式的過程中叫用了所有其他BaseHandler 的方法,因此這些方法主要存在是為了允許自定義整個過程。

以下方法必須在子類別中覆寫:

_write(data)

緩衝要傳送給用戶端的位元組data。如果這個方法實際上傳送了數據也是可以的;當底層系統實際具有這種區分時,BaseHandler 為了更好的效能進而分離寫入和刷新操作。

_flush()

強制將緩衝數據傳送到用戶端。如果這是一個無操作(no-op)的方法(即,如果_write() 實際上發送了數據),那麼是可以的。

get_stdin()

回傳一個與InputStream 相容的物件並適用於用作目前正在處理請求的wsgi.input

get_stderr()

回傳一個與ErrorStream 相容的物件並適用於用作目前正在處理請求的wsgi.errors

add_cgi_vars()

將目前請求的 CGI 變數插入到environ 屬性中。

以下是你可能希望覆寫的其他方法和屬性。這個列表只是一個摘要,然而,不包括可以被覆寫的每個方法。在嘗試建立自定義的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 副本,但子類別可以在類別或實例層級建立自己的副本。注意字典應該被視為唯讀,因為預設值在多個類別與實例中共享。

server_software

如果設置origin_server 屬性,則此屬性的值將用於設置預設的SERVER_SOFTWARE WSGI 環境變數,並且還將用於設置 HTTP 回應中的預設Server: 標頭。對於不是 HTTP origin 伺服器的處置程式(例如BaseCGIHandlerCGIHandler),此屬性將被忽略。

在 3.3 版的變更:將術語 "Python" 替換為特定實作的術語,如 "CPython"、"Jython" 等。

get_scheme()

回傳用於目前請求的 URL scheme。預設的實作使用wsgiref.util 中的guess_scheme() 函式去猜測 scheme 是 "http" 或是 "https",基於目前請求的environ 變數。

setup_environ()

environ 屬性設置為完全填充的 WSGI 環境。預設的實作使用上述所有方法和屬性,以及get_stdin()get_stderr()add_cgi_vars() 方法以及wsgi_file_wrapper 屬性。如果不呈現它也會插入一個SERVER_SOFTWARE 關鍵字,只要origin_server 屬性是一個 true 值並且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.exception() 存取目前的錯誤,當呼叫它(如PEP 3333 的 "Error Handling" 部分所描述)時應該傳遞資訊給start_response。特別是start_response 可呼叫物件應該遵循StartResponse 協定。

預設的實作只是使用error_statuserror_headerserror_body 屬性產生輸出頁面。子類別可以覆蓋此方法以生成更動態的錯誤輸出。

然而,從安全的角度並不建議向任何普通使用者顯示診斷資訊;理想情況下,你應該需要採取特殊措施才能啟用診斷輸出,這就是預設實作不包括任何診斷資訊的原因。

error_status

用於錯誤回應的 HTTP 狀態。這應該是一個按照PEP 3333 定義的狀態字串;預設為 500 狀態碼和訊息。

error_headers

用於錯誤回應的 HTTP 標頭。這應該是一個 WSGI 回應標頭的串列((name,value) 元組),如PEP 3333 中所描述。預設串列只設置內容種類為text/plain

error_body

錯誤回應的主體。這應該是一個 HTTP 回應內容的位元組字串。預設為純文字 "A server error occurred. Please contact the administrator."

用於PEP 3333 中的 "Optional Platform-Specific File Handling" 功能的方法和屬性:

wsgi_file_wrapper

一個wsgi.file_wrapper 工廠函式(factory),與wsgiref.types.FileWrapper 相容,或者為None。這個屬性的預設值是wsgiref.util.FileWrapper 類別。

sendfile()

覆蓋以實作特定平台的檔案傳輸。只有當應用程式的回傳值是由wsgi_file_wrapper 屬性指定的類別實例時才會呼叫此方法。如果它能夠成功傳輸檔案應該回傳一個 true 值,以便不執行預設的傳輸程式碼。該方法的預設實作只回傳一個 false 值。

其他方法和屬性:

origin_server

這個屬性應該被設置為 true 值,如果處理程式(handler)的_write()_flush() 被用於直接與用戶端通訊,而不是透過 CGI-like 的閘道協議希望 HTTP 狀態在特殊的Status: 標頭中。

這個屬性在BaseCGIHandler 預設值為 true,但是在BaseCGIHandlerCGIHandler 為 false。

http_version

如果origin_server 為 true,則此字串屬性用於設定傳送給用戶端的回應的 HTTP 版本。預設為"1.0"

wsgiref.handlers.read_environ()

os.environ 轉碼 CGI 變數到PEP 3333 中的 "bytes in unicode" 字串,並回傳一個新字典。這個函式被CGIHandlerIISCGIHandler 使用來直接替代os.environ,在所有平台和使用 Python 3 的網頁伺服器上不一定符合 WSGI 標準,具體來說,在 OS 的實際環境是 Unicode(例如 Windows)的情況下,或者在環境是位元組的情況下,但 Python 用於解碼它的系統編碼不是 ISO-8859-1 (例如使用 UTF-8 的 Unix 系統)。

如果你自己正在實作 CGI-based 處理程式(handler),你可能想要使用這個函式來替換單純直接從os.environ 中複製值。

在 3.2 版被加入.

wsgiref.types -- 用於靜態型別檢查的 WSGI 型別

這個模組提供在PEP 3333 中所描述的各種用於靜態型別檢查的型別。

在 3.11 版被加入.

classwsgiref.types.StartResponse

一個描述start_response() 可呼叫物件的typing.Protocol (PEP 3333)。

wsgiref.types.WSGIEnvironment

一個描述 WSGI 環境字典的型別別名。

wsgiref.types.WSGIApplication

一個描述 WSGI 應用程式可呼叫物件的型別別名。

classwsgiref.types.InputStream

一個描述WSGI 輸入串流typing.Protocol

classwsgiref.types.ErrorStream

一個描述WSGI 錯誤串流typing.Protocol

classwsgiref.types.FileWrapper

一個描述檔案包裝器typing.Protocol。請參閱wsgiref.util.FileWrapper 來瞭解此協議的具體實作。

範例

This is a working "Hello World" WSGI application, where thestart_responsecallable should follow theStartResponse protocol:

"""Every WSGI application must have an application object - a callableobject that accepts two arguments. For that purpose, we're going touse a function (note that you're not limited to a function, you canuse a class for example). The first argument passed to the functionis a dictionary containing CGI-style environment variables and thesecond variable is the callable object."""fromwsgiref.simple_serverimportmake_serverdefhello_world_app(environ,start_response):status="200 OK"# HTTP Statusheaders=[("Content-type","text/plain; charset=utf-8")]# HTTP Headersstart_response(status,headers)# The returned object is going to be printedreturn[b"Hello World"]withmake_server("",8000,hello_world_app)ashttpd:print("Serving on port 8000...")# Serve until process is killedhttpd.serve_forever()

提供目前目錄的 WSGI 應用程式範例,並接受命令列上的可選目錄和埠號(預設:8000):

"""Small wsgiref based web server. Takes a path to serve from and anoptional port number (defaults to 8000), then tries to serve files.MIME types are guessed from the file names, 404 errors are raisedif the file is not found."""importmimetypesimportosimportsysfromwsgirefimportsimple_server,utildefapp(environ,respond):# Get the file name and MIME typefn=os.path.join(path,environ["PATH_INFO"][1:])if"."notinfn.split(os.path.sep)[-1]:fn=os.path.join(fn,"index.html")mime_type=mimetypes.guess_file_type(fn)[0]# Return 200 OK if file exists, otherwise 404 Not Foundifos.path.exists(fn):respond("200 OK",[("Content-Type",mime_type)])returnutil.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 argumentspath=sys.argv[1]iflen(sys.argv)>1elseos.getcwd()port=int(sys.argv[2])iflen(sys.argv)>2else8000# Make and start the server until control-chttpd=simple_server.make_server("",port,app)print(f"Serving{path} on port{port}, control-C to stop")try:httpd.serve_forever()exceptKeyboardInterrupt:print("Shutting down.")httpd.server_close()