源碼:Lib/wsgirefhtml
Web服務器網關接口(Web Server Gateway Interface, WSGI),是用Python
寫的一個服務器軟件和web應用之間的通用接口。使用通用接口,可以使同一個應用方便的被不一樣過的web服務器調用。python
只有web服務器和軟件框架做者須要知道WSGI
設計的細節和極端狀況。你只須要安裝一個WSGI
應用或者用現有框架寫一個web應用,並不須要知道WSGI
的所有細節。git
wsgiref
是WSGI
細則的一個參考實現,用於給web服務器和框架提供WSGI
支持。它提供了處理WSGI
環境變量、response
頭和WSGI
服務器基類的功能,一個服務於WSGI
應用的HTTP服務器demo,以及檢測WSGI
服務器和應用是否和WSGI
細則(PEP 3333
)是否一致的驗證工具。github
去wsgi
官網獲取更多信息和相關教程。web
wsgiref.util
- WSGI環境工具本模塊提供了一些列用於WSGI
環境的適用功能。 根據PEP 3333
, WSGI
環境是一個包含HTTP請求變量的字典。全部接受environ
參數的函數都預期接受一個兼容於WSGI
的字典。詳見PEP 3333
。算法
wsgiref.util.guess_scheme(environ)
經過檢查環境變量中的HTTPS
,返回wsgi.url_scheme
是http
仍是https
。
這個函數用於,建立一個包裝CGI
或者FastCGI
協議的網關。通常來講,提供這些協議的服務器,當使用SSL時,會提供一個值爲"1", "yes"或者"on"的HTTPS
變量。若是找到了,這個函數返回'https';不然,返回'http'。api
wsgiref.util.request_uri(environ, include_query=True)
返回請求的URI
,可選參數決定是否返回查詢字符串,使用PEP 3333
中的"URL Reconstruction"算法。服務器
wsgiref.util.application_uri(environ)
與request_uri
方法相似,除了忽略PATH_INFO
還有QUERY_STRING
變量。返回結果爲發起請求的應用對象的基地址(base uri
)。app
wsgiref.util.shift_pathi_info(environ)
將環境變量中PAHT_INFO
移動一個名字到SCRIPT_NAME
,並返回。環境變量會被原地修改,若是你要保存原始值,存一個備份 。
若是PAHT_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
。
當路徑僅爲"/"
時,該例行程序返回空字符串,並在SCRIPT_NAME
處添加末尾斜槓。儘管空路徑片斷通常都被忽略了。但SCRIPT_NAME
通常不以斜槓結束。故意這樣設計,是爲了讓應用在作對象遍歷時,可以區分/x
和/x/
這兩個不一樣的路徑。框架
# 源碼 # https://github.com/python/cpython/blob/master/Lib/wsgiref/util.py#L102 if not name and not script_name.endswith('/'): script_name += '/'
wsgiref.util.setup_testing_defaults(environ)
爲了測試而更新環境變量。
這個例行程序爲WSGI添加各類參數,包括HTTP_HOST
, SERVER_NAME
, SERVER_PORT
, REQUESTS_METHOD
, SCRIPT_NAME
。以及PEP 3333中頂以的全部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; charset=utf-8')] # 發送頭部 start_response(status, headers) ret = [("%s: %s\n" % (key, value)).encode("utf-8") for key, value in environ.items()] return ret # 這行代碼我在3.6.1下運行會出錯,make_server不支持上下文管理? # 把with 語句改爲普通的語句好像就沒問題了。 with make_server('', 8000, simple_app) as httpd: print("Serving on port 8000...") httpd.serve_forever()
除了上述函數,wsgiref.util
還提供了其餘各類功能。
wsgiref.util.is_hop_by_hop(header_name)
根據[RFC 2616](https://tools.ietf.org/html/rfc2616.html),若是`header_name`是`"Hop-by-Hop"`返回True.
wsgiref.util.FileWrapper(filelike, blksize=8192)
一個把類文件對象轉變爲成迭代器的包裝器。結果支持`__getitem__()`和`__iter__()`。當迭代遍歷這個對象時,`blksize`參數會被重複地傳給類文件對象地`read()`方法,獲取產生的字節。當`read()`產生空字節時,迭代結束。 若是這個類文件對象有`close()`方法,返回的對象也有`close()`方法,當被調用時,會激活類文件對象的`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)
wsgi.headers
WSGI response 頭工具本模塊只提供一個類:Headers
。使用(mapping-like interface)映射接口, 方便操做地操做WSGI地響應頭。
wsgiref.headers.Headers([headers])
類建立一個映射對象包裝headers。 headers,必須是按照PEP 3333中所規定地鍵值元組列表。默認值時一個空列表。】
Headers
對象支持映射操做,包括__getitem()
, get()
, __setitem()
, setdefault()
, __delitem()
, 以及__contain__()
。key是name,值是該name下的第一個值。
與字典不一樣,在你試圖刪除或者get一個不存在key時,Headers
對象不會拋出異常。Headers
的長度等於它items()
的長度,
bytes()
函數,返回一個格式化的字符串,用於傳輸HTTP
響應頭。每一個頭佔一行,用冒號和控開關白分割。行爲時回車+換行。結尾是一個空行
get_all(name)
返回對應name下全部的值
返回順序爲他們在最初的頭中的位置,或者他們被添加進實例的順序。可能會重複。
add_header(name, value, **_params)
添加一個頭,經過關鍵詞參數能夠添加MIME參數。
在參數名裏的下劃線會被轉換成鏈接符。由於鏈接符在python標識符中不合法,但在MIME參數中有不少鏈接符。
wsgiref.simple_server
一個簡單的WSGI HTTP服務器本模塊提供了一個簡單的基於http.server
的,可服務於WSGI應用的HTTP服務器。每個服務器實例,在一個給定的主機和端口上服務於一個WSGI應用。若是你想在一個主機和端口上,服務於多個應用,你應當建立一個WSGI應用,解析PATH_INFO
決定對於每一個請求,應該選擇哪一個應用。
wsgiref.simple_server.make_server(host, port, app, server_class=WSGIServer, handle_class=WSGIRequestHandler)
在指定host和port上,建立一個新的WSGI服務器,接受來自app的鏈接。返回值是傳入的server_class
的一個實例。並會使用handler_class
處理requests。app
參數必須是一個符合PEP 3333定義的WSGI應用對象。
wsgirfe.simple_server.demo_app(environ, start_response)
本函數是一個小而徹底的WSGI程序,返回一個包含"Hello world!"和環境變量k-v值對的文本頁。用於確認WSGI服務器可以爭取的處理WSGI程序。
wsgiref.simple_server.WSGIServer(server_address, RequestsHandlerClass)
類建立一個WSGISever實例,server_address
應當是(host, port)元組,RequestHandlerClass
應當是http.server.BasedHTTPRequestHandler
的子類,用於處理requests。
你不須要正式調用構造器,由於make_server()
函數會幫你處理細節。
WSGIServer
是http.server.HTTPServer
的子類,因此繼承了其方法,如:serve_forever()
和handle_request()
。WSGIServer
同時也提供了一些WSGI
專有的方法。好比:
set_app(application)
設置一個可調用應用,做爲接收requests的WSGI應用。
get_app()
返回目前設置的可調用應用。
通常來講,你不要調用這些額外的方法。 set_app()
通常有make_server()
調用,get_app()
主要是爲了requests handler實例而存在。
wsgiref.simple_server.WSGIRequestHandler(reqeust, client_address, server)
類對於給定的request(例如,一個socket), client_address (一個(host, port)元組)server,建立一個HTTP handler。
你不須要直接建立這個類的實例,他們會由WSGIServer
對象按需建立。單你能夠建立一個該類的子類,做爲handler_class參數,傳給make_server()
函數。如下爲一些在子類中可能相關的須要重寫的函數。
get_environ()
返回一個包含WSGI環境的字典。默認設置返回WSGIServer對象的base_environ
字典屬性,並加上來自HTTP request的各類頭部。每次調用這個方法,都會放回一個新的字典,包含各類PEP 3333中規定的CGI環境變量。
get_stderr()
返回被用做wsgi.errors
流的對象。默認設置返回sys.stderr
。
handle()
處理HTTP請求,默認這是使用wsgiref.hanlder
類建立一個handler實例,執行真實的WSGI應用接口。
wsgirref.validate
WSGI一致性檢查器當建立新的WSGI應用對象、框架、服務器和中間件時,用wsgiref.validate
檢查新代碼是否可用是很是有用過的。本模塊提供了一個能建立WSGI應用對象的函數,使WSGI服務器和WSGI應用對象可以正常通訊,檢查兩側協議的一致性。
注意這個應用不保證徹底符合PEP 3333。這個模塊不報錯,不意味着確定沒錯。可是,若是這個模塊報錯,就意味着確定有錯誤。不是100%兼容。
這個模塊基於Python Paste
。
包裝application並返回一個新的WSGI應用對象,返回的應用將會把全部的請求發送給最初的應用。而且檢查這個應用和啓動它的服務器是否遵循WSGI規則和RFC 2616
任何檢測到的不一致的結果,都會拋出一個AssertionError
。但,如何處理這些異常取決於服務器。好比,wsgiref.simple_server
和提早基於wsgiref.handlers
的服務器,會直接輸出錯誤信息,將回溯信息輸出到sys.stderr
或者其餘錯誤流中。
這個包裝器也可能用warning
模塊指明那些有問題的,但不徹底違反PEP 3333的行爲。除非用Python命令行選項或者是warning
的api禁止,這些細心會被輸出至sys.stderr
。
wsgirf.handlers
服務器/網管基類這個模塊提供了配置WSGI服務器和網關的基類。這些基類處理了大部分與一個WSGI應用之間的通訊,只要給與了他們一個CGI樣的環境,以及輸入/輸出及錯誤流。
wsgiref.hanlder.CGIHandler
類經過sys.stdin
, sys.stdout
, sys.stderr
和os.environ
喚起CGI。當你想要經過一個CGI腳本運行一個WSGI程序時頗有用。你可使用CGIHandler().run(app)
。
這個類是BaseCGIHandler
的子類,並將wsgi.run()=True, wsgi.multithread=False, wsgi.multiprocess=True
,並使用sys
和os
獲取必要的CGI流和環境。(參見CGI部分和前驅知識)
wsgiref.handler.IISCGIHandler
類在微軟的IIS
服務器上激活CGIHandler
。
wsgiref.handlers.BaseCGIHandler()
類和CGIHandler
類 相似。
wsgiref.handlers.BaseHandler
一個抽象類。每一個實例處理一個HTTP請求。儘管原則上你能夠建立一個子類,從而能被多個請求服用。
只有一個方法能被外部調用。
run(app)