簡介
HTTPServer 是 socketserver.TCPServer 的一個(gè)子類。它會(huì)創(chuàng)建和偵聽 HTTP 套接字,并將請求分發(fā)給處理程序。創(chuàng)建和運(yùn)行 HTTP 服務(wù)器的代碼類似如下所示:
def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
server_address = ('', 8000)
httpd = server_class(server_address, handler_class)
httpd.serve_forever()
class http.server.HTTPServer(server_address, RequestHandlerClass)
該類基于 TCPServer 類,并在實(shí)例變量 server_name 和 server_port 中保存 HTTP 服務(wù)器地址。處理程序可通過實(shí)例變量 server 訪問 HTTP 服務(wù)器。
class http.server.ThreadingHTTPServer(server_address, RequestHandlerClass)
該類相似于 HTTPServer ,只是會(huì)利用 ThreadingMixIn 對(duì)請求進(jìn)行多線程處理。當(dāng)需要對(duì) Web 瀏覽器預(yù)先打開套接字進(jìn)行處理時(shí),這就很有用,這時(shí) HTTPServer 會(huì)一直等待請求。
3.7 新版功能.
實(shí)例化 HTTPServer 和 ThreadingHTTPServer 時(shí),必須給出一個(gè) RequestHandlerClass,本模塊提供了該對(duì)象的三種變體:
class http.server.BaseHTTPRequestHandler(request, client_address, server)
這個(gè)類用于處理到達(dá)服務(wù)器的 HTTP 請求。 它本身無法響應(yīng)任何實(shí)際的 HTTP 請求;它必須被子類化以處理每個(gè)請求方法(例如 GET 或 POST)。 BaseHTTPRequestHandler 提供了許多供子類使用的類和實(shí)例變量以及方法。
這個(gè)處理程序?qū)⒔馕稣埱蠛蜆?biāo)頭,然后調(diào)用特定請求類型對(duì)應(yīng)的方法。 方法名稱將根據(jù)請求來構(gòu)造。 例如,對(duì)于請求方法 SPAM,將不帶參數(shù)地調(diào)用 do_SPAM() 方法。 所有相關(guān)信息會(huì)被保存在該處理程序的實(shí)際變量中。 子類不需要重載或擴(kuò)展 init() 方法。
BaseHTTPRequestHandler 具有下列實(shí)例變量:
client_address
包含 (host, port) 形式的指向客戶端地址的元組。
server
包含服務(wù)器實(shí)例。
close_connection
應(yīng)當(dāng)在 handle_one_request() 返回之前設(shè)定的布爾值,指明是否要期待另一個(gè)請求,還是應(yīng)當(dāng)關(guān)閉連接。
requestline
包含 HTTP 請求行的字符串表示。 末尾的 CRLF 會(huì)被去除。 該屬性應(yīng)當(dāng)由 handle_one_request() 來設(shè)定。 如果無有效請求行被處理,則它應(yīng)當(dāng)被設(shè)為空字符串。
command
包含具體的命令(請求類型)。 例如 ‘GET’。
path
包含請求路徑。如果URL的查詢部分存在, path 會(huì)包含這個(gè)查詢部分。使用 RFC 3986 的術(shù)語來說,在這里, path 包含 hier-part 和 query 。
request_version
包含請求的版本字符串。 例如 ‘HTTP/1.0’。
headers
存放由 MessageClass 類變量所指定的類的實(shí)例。 該實(shí)例會(huì)解析并管理 HTTP 請求中的標(biāo)頭。 http.client 中的 parse_headers() 函數(shù)將被用來解析標(biāo)頭并且它需要 HTTP 請求提供一個(gè)有效的 RFC 2822 風(fēng)格的標(biāo)頭。
rfile
一個(gè) io.BufferedIOBase 輸入流,準(zhǔn)備從可選的輸入數(shù)據(jù)的開頭進(jìn)行讀取。
wfile
包含用于寫入響應(yīng)并發(fā)回給客戶端的輸出流。 在寫入流時(shí)必須正確遵守 HTTP 協(xié)議以便成功地實(shí)現(xiàn)與 HTTP 客戶端的互操作。
在 3.6 版更改: 這是一個(gè) io.BufferedIOBase 流。
BaseHTTPRequestHandler 具有下列屬性:
server_version
指定服務(wù)器軟件版本。 你可能會(huì)想要重載該屬性。 該屬性的格式為多個(gè)以空格分隔的字符串,其中每個(gè)字符串的形式為 name[/version]。 例如 ‘BaseHTTP/0.2’。
sys_version
包含 Python 系統(tǒng)版本,采用 version_string 方法和 server_version 類變量所支持的形式。 例如 ‘Python/1.4’。
error_message_format
指定應(yīng)當(dāng)被 send_error() 方法用來構(gòu)建發(fā)給客戶端的錯(cuò)誤響應(yīng)的格式字符串。 該字符串應(yīng)使用來自 responses 的變量根據(jù)傳給 send_error() 的狀態(tài)碼來填充默認(rèn)值。
error_content_type
指定發(fā)送給客戶端的錯(cuò)誤響應(yīng)的 Content-Type HTTP 標(biāo)頭。 默認(rèn)值為 ‘text/html’。
protocol_version
MessageClass
指定一個(gè) email.message.Message 這樣的類來解析 HTTP 標(biāo)頭。 通常該屬性不會(huì)被重載,其默認(rèn)值為 http.client.HTTPMessage。
responses
該屬性包含一個(gè)整數(shù)錯(cuò)誤代碼與由短消息和長消息組成的二元組的映射。 例如,{code: (shortmessage, longmessage)}。 shortmessage 通常是作為消息響應(yīng)中的 message 鍵,而 longmessage 則是作為 explain 鍵。 該屬性會(huì)被 send_response_only() 和 send_error() 方法所使用。
BaseHTTPRequestHandler 實(shí)例具有下列方法:
handle()
調(diào)用 handle_one_request() 一次(或者如果啟用了永久連接則為多次)來處理傳入的 HTTP 請求。 你應(yīng)該完全不需要重載它;而是要實(shí)現(xiàn)適當(dāng)?shù)?do_*() 方法。
handle_one_request()
此方法將解析并將請求分配給適當(dāng)?shù)?do_*() 方法。 你應(yīng)該完全不需要重載它。
handle_expect_100()
3.2 新版功能.
send_error(code, message=None, explain=None)
發(fā)送并記錄回復(fù)給客戶端的完整錯(cuò)誤信息。 數(shù)字形式的 code 指明 HTTP 錯(cuò)誤代碼,可選的 message 為簡短的易于人類閱讀的錯(cuò)誤描述。 explain 參數(shù)可被用于提供更詳細(xì)的錯(cuò)誤信息;它將使用 error_message_format 屬性來進(jìn)行格式化并在一組完整的標(biāo)頭之后作為響應(yīng)體被發(fā)送。 responses 屬性存放了 message 和 explain 的默認(rèn)值,它們將在未提供時(shí)被使用;對(duì)于未知代碼兩者的默認(rèn)值均為字符串 ???。 如果方法為 HEAD 或響應(yīng)代碼是下列值之一則響應(yīng)體將為空: 1xx, 204 No Content, 205 Reset Content, 304 Not Modified。
在 3.4 版更改: 錯(cuò)誤響應(yīng)包括一個(gè) Content-Length 標(biāo)頭。 增加了 explain 參數(shù)。
send_response(code, message=None)
將一個(gè)響應(yīng)標(biāo)頭添加到標(biāo)頭緩沖區(qū)并記錄被接受的請求。 HTTP 響應(yīng)行會(huì)被寫入到內(nèi)部緩沖區(qū),后面是 Server 和 Date 標(biāo)頭。 這兩個(gè)標(biāo)頭的值將分別通過 version_string() 和 date_time_string() 方法獲取。 如果服務(wù)器不打算使用 send_header() 方法發(fā)送任何其他標(biāo)頭,則 send_response() 后面應(yīng)該跟一個(gè) end_headers() 調(diào)用。
在 3.3 版更改: 標(biāo)頭會(huì)被存儲(chǔ)到內(nèi)部緩沖區(qū)并且需要顯式地調(diào)用 end_headers()。
send_header(keyword, value)
將 HTTP 標(biāo)頭添加到內(nèi)部緩沖區(qū),它將在 end_headers() 或 flush_headers() 被發(fā)起調(diào)用時(shí)寫入輸出流。 keyword 應(yīng)當(dāng)指定標(biāo)頭關(guān)鍵字,并以 value 指定其值。 請注意,在 send_header 調(diào)用結(jié)束之后,必須調(diào)用 end_headers() 以便完成操作。
在 3.2 版更改: 標(biāo)頭將被存入內(nèi)部緩沖區(qū)。
send_response_only(code, message=None)
只發(fā)送響應(yīng)標(biāo)頭,用于當(dāng) 100 Continue 響應(yīng)被服務(wù)器發(fā)送給客戶端的場合。 標(biāo)頭不會(huì)被緩沖而是直接發(fā)送到輸出流。 如果未指定 message,則會(huì)發(fā)送與響應(yīng) code 相對(duì)應(yīng)的 HTTP 消息。
3.2 新版功能.
end_headers()
將一個(gè)空行(指明響應(yīng)中 HTTP 標(biāo)頭的結(jié)束)添加到標(biāo)頭緩沖區(qū)并調(diào)用 flush_headers()。
在 3.2 版更改: 已緩沖的標(biāo)頭會(huì)被寫入到輸出流。
flush_headers()
最終將標(biāo)頭發(fā)送到輸出流并清空內(nèi)部標(biāo)頭緩沖區(qū)。
3.3 新版功能.
log_request(code=‘-’, size=‘-’)
記錄一次被接受(成功)的請求。 code 應(yīng)當(dāng)指定與請求相關(guān)聯(lián)的 HTTP 代碼。 如果請求的大小可用,則它應(yīng)當(dāng)作為 size 形參傳入。
log_error(…)
當(dāng)請求無法完成時(shí)記錄一次錯(cuò)誤。 默認(rèn)情況下,它會(huì)將消息傳給 log_message(),因此它接受同樣的參數(shù) (format 和一些額外的值)。
log_message(format, …)
將任意一條消息記錄到 sys.stderr。 此方法通常會(huì)被重載以創(chuàng)建自定義的錯(cuò)誤日志記錄機(jī)制。 format 參數(shù)是標(biāo)準(zhǔn) printf 風(fēng)格的格式字符串,其中會(huì)將傳給 log_message() 的額外參數(shù)用作格式化操作的輸入。 每條消息日志記錄的開頭都會(huì)加上客戶端 IP 地址和當(dāng)前日期時(shí)間。
version_string()
返回服務(wù)器軟件的版本字符串。 該值為 server_version 與 sys_version 屬性的組合。
date_time_string(timestamp=None)
返回由 timestamp 所給定的日期和時(shí)間(參數(shù)應(yīng)為 None 或?yàn)?time.time() 所返回的格式),格式化為一個(gè)消息標(biāo)頭。 如果省略 timestamp,則會(huì)使用當(dāng)前日期和時(shí)間。
結(jié)果看起來像 ‘Sun, 06 Nov 1994 08:49:37 GMT’。
log_date_time_string()
返回當(dāng)前的日期和時(shí)間,為日志格式化
address_string()
返回客戶端的地址
在 3.3 版更改: 在之前版本中,會(huì)執(zhí)行一次名稱查找。 為了避免名稱解析的時(shí)延,現(xiàn)在將總是返回 IP 地址。
class http.server.SimpleHTTPRequestHandler(request, client_address, server, directory=None)
這個(gè)類會(huì)為目錄 directory 及以下的文件提供發(fā)布服務(wù),或者如果未提供 directory 則為當(dāng)前目錄,直接將目錄結(jié)構(gòu)映射到 HTTP 請求。
3.7 新版功能: directory 形參。
在 3.9 版更改: directory 形參接受一個(gè) path-like object。
諸如解析請求之類的大量工作都是由基類 BaseHTTPRequestHandler 完成的。本類實(shí)現(xiàn)了 do_GET() 和 do_HEAD() 函數(shù)。
以下是 SimpleHTTPRequestHandler 的類屬性。
server_version
這會(huì)是 “SimpleHTTP/” + version,其中 version 定義于模塊級(jí)別。
extensions_map
將后綴映射為 MIME 類型的字典,其中包含了覆蓋系統(tǒng)默認(rèn)值的自定義映射關(guān)系。不區(qū)分大小寫,因此字典鍵只應(yīng)為小寫值。
在 3.9 版更改: 此字典不再填充默認(rèn)的系統(tǒng)映射,而只包含覆蓋值。
SimpleHTTPRequestHandler 類定義了以下方法:
do_HEAD()
本方法為 ‘HEAD’ 請求提供服務(wù):它將發(fā)送等同于 GET 請求的頭文件。關(guān)于合法頭部信息的更完整解釋,請參閱 do_GET() 方法。
do_GET()
通過將請求解釋為相對(duì)于當(dāng)前工作目錄的路徑,將請求映射到某個(gè)本地文件。
如果請求被映射到目錄,則會(huì)依次檢查該目錄是否存在 index.html 或 index.htm 文件。若存在則返回文件內(nèi)容;否則會(huì)調(diào)用 list_directory() 方法生成目錄列表。本方法將利用 os.listdir() 掃描目錄,如果 listdir() 失敗,則返回 404 出錯(cuò)應(yīng)答。
如果請求被映射到文件,則會(huì)打開該文件。 打開文件時(shí)的任何 OSError 異常都會(huì)被映射為 404, ‘File not found’ 錯(cuò)誤。 如果請求中帶有 ‘If-Modified-Since’ 標(biāo)頭,而在此時(shí)間點(diǎn)之后文件未作修改,則會(huì)發(fā)送 304, ‘Not Modified’ 的響應(yīng)。 否則會(huì)調(diào)用 guess_type() 方法猜測內(nèi)容的類型,該方法會(huì)反過來用到 extensions_map 變量,并返回文件內(nèi)容。
將會(huì)輸出 ‘Content-type:’ 頭部信息,帶上猜出的內(nèi)容類型,然后是 ‘Content-Length:’ 頭部信息,帶有文件的大小,以及 ‘Last-Modified:’ 頭部信息,帶有文件的修改時(shí)間。
后面是一個(gè)空行,標(biāo)志著頭部信息的結(jié)束,然后輸出文件的內(nèi)容。如果文件的 MIME 類型以 text/ 開頭,文件將以文本模式打開;否則將使用二進(jìn)制模式。
For example usage, see the implementation of the test function in Lib/http/server.py.
在 3.7 版更改: 為 ‘If-Modified-Since’ 頭部信息提供支持。
SimpleHTTPRequestHandler 類的用法可如下所示,以便創(chuàng)建一個(gè)非常簡單的 Web 服務(wù),為相對(duì)于當(dāng)前目錄的文件提供服務(wù):
import http.server
import socketserver
PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print("serving at port", PORT)
httpd.serve_forever()
http.server 也可以使用解釋器的 -m 參數(shù)直接調(diào)用。 與前面的例子類似,這將提供相對(duì)于當(dāng)前目錄的文件:
python -m http.server
服務(wù)器默認(rèn)監(jiān)聽端口為8000??梢酝ㄟ^傳遞所需的端口號(hào)作為參數(shù)來覆蓋默認(rèn)值:
python -m http.server 9000
默認(rèn)情況下,服務(wù)器將自己綁定到所有接口。 選項(xiàng) -b/–bind 指定了一個(gè)特定的地址,它應(yīng)該與之綁定。 IPv4 和 IPv6 地址都被支持。例如,下面的命令使服務(wù)器只綁定到 localhost:
python -m http.server --bind 127.0.0.1
3.4 新版功能: 引入了 --bind 參數(shù)。
3.8 新版功能: 為了支持 IPv6 改進(jìn)了 --bind 參數(shù)。
默認(rèn)情況下,服務(wù)器使用當(dāng)前目錄。選項(xiàng) -d/–directory 指定了一個(gè)它應(yīng)該提供文件的目錄。例如,下面的命令使用一個(gè)特定的目錄:
python -m http.server --directory /tmp/
3.7 新版功能: --directory 參數(shù)被引入。
python -m http.server --protocol HTTP/1.1
3.11 新版功能: --protocol argument was introduced.
class http.server.CGIHTTPRequestHandler(request, client_address, server)
該類可為當(dāng)前及以下目錄中的文件或輸出 CGI 腳本提供服務(wù)。注意,把 HTTP 分層結(jié)構(gòu)映射到本地目錄結(jié)構(gòu),這與 SimpleHTTPRequestHandler 完全一樣。
備注 由 CGIHTTPRequestHandler 類運(yùn)行的 CGI 腳本不能進(jìn)行重定向操作(HTTP 代碼302),因?yàn)樵趫?zhí)行 CGI 腳本之前會(huì)發(fā)送代碼 200(接下來就輸出腳本)。這樣狀態(tài)碼就沖突了。
然而,如果這個(gè)類猜測它是一個(gè) CGI 腳本,那么就會(huì)運(yùn)行該 CGI 腳本,而不是作為文件提供出去。 只會(huì)識(shí)別基于目錄的 CGI —— 另有一種常用的服務(wù)器設(shè)置,即標(biāo)識(shí) CGI 腳本是通過特殊的擴(kuò)展名。
如果請求指向 cgi_directories 以下的路徑,do_GET() 和 do_HEAD() 函數(shù)已作修改,不是給出文件,而是運(yùn)行 CGI 腳本并輸出結(jié)果。
CGIHTTPRequestHandler 定義了以下數(shù)據(jù)成員:
cgi_directories
默認(rèn)為 [‘/cgi-bin’, ‘/htbin’],視作 CGI 腳本所在目錄。
CGIHTTPRequestHandler 定義了以下方法:
do_POST()
本方法服務(wù)于 ‘POST’ 請求,僅用于 CGI 腳本。如果試圖向非 CGI 網(wǎng)址發(fā)送 POST 請求,則會(huì)輸出錯(cuò)誤 501:Can only POST to CGI scripts"。
請注意,為了保證安全性,CGI 腳本將以用戶 nobody 的 UID 運(yùn)行。CGI 腳本運(yùn)行錯(cuò)誤將被轉(zhuǎn)換為錯(cuò)誤 403。
通過在命令行傳入 --cgi 參數(shù),可以啟用 CGIHTTPRequestHandler :
python -m http.server --cgi
安全考量
SimpleHTTPRequestHandler在處理請求時(shí)將遵循符號(hào)鏈接,這使得可以為指定目錄之外的文件提供服務(wù)。
早期版本的Python沒有清除從Python-m http.server或默認(rèn)BaseHTTPRequestHandler.log_message實(shí)現(xiàn)發(fā)送到stderr的日志消息中的控制字符。這可能允許連接到服務(wù)器的遠(yuǎn)程客戶端向您的終端發(fā)送惡意控制代碼。文章來源:http://www.zghlxwxcb.cn/news/detail-720506.html
3.11.1 新版功能: 在stderr日志中清除控制字符。文章來源地址http://www.zghlxwxcb.cn/news/detail-720506.html
到了這里,關(guān)于python:http.server --- HTTP 服務(wù)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!