http.server --- HTTP 服務(wù)器?

源代碼: Lib/http/server.py


這個(gè)模塊定義了用于實(shí)現(xiàn) HTTP 服務(wù)器的類(lèi)。

警告

不推薦在生產(chǎn)環(huán)境中使用 http.server 。它只實(shí)現(xiàn)了基本的安全檢查功能。

HTTPServersocketserver.TCPServer 的一個(gè)子類(lèi)。它會(huì)創(chuàng)建和偵聽(tīng) HTTP 套接字,并將請(qǐng)求分發(fā)給處理程序。創(chuàng)建和運(yùn)行 HTTP 服務(wù)器的代碼類(lèi)似如下所示:

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)?

該類(lèi)基于 TCPServer 類(lèi),并在實(shí)例變量 server_nameserver_port 中保存 HTTP 服務(wù)器地址。處理程序可通過(guò)實(shí)例變量 server 訪問(wèn) HTTP 服務(wù)器。

class http.server.ThreadingHTTPServer(server_address, RequestHandlerClass)?

該類(lèi)相似于 HTTPServer ,只是會(huì)利用 ThreadingMixIn 對(duì)請(qǐng)求進(jìn)行多線程處理。當(dāng)需要對(duì) Web 瀏覽器預(yù)先打開(kāi)套接字進(jìn)行處理時(shí),這就很有用,這時(shí) HTTPServer 會(huì)一直等待請(qǐng)求。

3.7 新版功能.

實(shí)例化 HTTPServerThreadingHTTPServer 時(shí),必須給出一個(gè) RequestHandlerClass,本模塊提供了該對(duì)象的三種變體:

class http.server.BaseHTTPRequestHandler(request, client_address, server)?

這個(gè)類(lèi)用于處理到達(dá)服務(wù)器的 HTTP 請(qǐng)求。 它本身無(wú)法響應(yīng)任何實(shí)際的 HTTP 請(qǐng)求;它必須被子類(lèi)化以處理每個(gè)請(qǐng)求方法(例如 GET 或 POST)。 BaseHTTPRequestHandler 提供了許多供子類(lèi)使用的類(lèi)和實(shí)例變量以及方法。

這個(gè)處理程序?qū)⒔馕稣?qǐng)求和標(biāo)頭,然后調(diào)用特定請(qǐng)求類(lèi)型對(duì)應(yīng)的方法。 方法名稱(chēng)將根據(jù)請(qǐng)求來(lái)構(gòu)造。 例如,對(duì)于請(qǐng)求方法 SPAM,將不帶參數(shù)地調(diào)用 do_SPAM() 方法。 所有相關(guān)信息會(huì)被保存在該處理程序的實(shí)際變量中。 子類(lèi)不需要重載或擴(kuò)展 __init__() 方法。

BaseHTTPRequestHandler 具有下列實(shí)例變量:

client_address?

包含 (host, port) 形式的指向客戶(hù)端地址的元組。

server?

包含服務(wù)器實(shí)例。

close_connection?

應(yīng)當(dāng)在 handle_one_request() 返回之前設(shè)定的布爾值,指明是否要期待另一個(gè)請(qǐng)求,還是應(yīng)當(dāng)關(guān)閉連接。

requestline?

包含 HTTP 請(qǐng)求行的字符串表示。 末尾的 CRLF 會(huì)被去除。 該屬性應(yīng)當(dāng)由 handle_one_request() 來(lái)設(shè)定。 如果無(wú)有效請(qǐng)求行被處理,則它應(yīng)當(dāng)被設(shè)為空字符串。

command?

包含具體的命令(請(qǐng)求類(lèi)型)。 例如 'GET'。

path?

包含請(qǐng)求路徑。如果URL的查詢(xún)部分存在, path 會(huì)包含這個(gè)查詢(xún)部分。使用 RFC 3986 的術(shù)語(yǔ)來(lái)說(shuō),在這里, path 包含 hier-partquery 。

request_version?

包含請(qǐng)求的版本字符串。 例如 'HTTP/1.0'。

headers?

存放由 MessageClass 類(lèi)變量所指定的類(lèi)的實(shí)例。 該實(shí)例會(huì)解析并管理 HTTP 請(qǐng)求中的標(biāo)頭。 http.client 中的 parse_headers() 函數(shù)將被用來(lái)解析標(biāo)頭并且它需要 HTTP 請(qǐng)求提供一個(gè)有效的 RFC 2822 風(fēng)格的標(biāo)頭。

rfile?

一個(gè) io.BufferedIOBase 輸入流,準(zhǔn)備從可選的輸入數(shù)據(jù)的開(kāi)頭進(jìn)行讀取。

wfile?

包含用于寫(xiě)入響應(yīng)并發(fā)回給客戶(hù)端的輸出流。 在寫(xiě)入流時(shí)必須正確遵守 HTTP 協(xié)議以便成功地實(shí)現(xiàn)與 HTTP 客戶(hù)端的互操作。

在 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 類(lèi)變量所支持的形式。 例如 'Python/1.4'

error_message_format?

指定應(yīng)當(dāng)被 send_error() 方法用來(lái)構(gòu)建發(fā)給客戶(hù)端的錯(cuò)誤響應(yīng)的格式字符串。 該字符串應(yīng)使用來(lái)自 responses 的變量根據(jù)傳給 send_error() 的狀態(tài)碼來(lái)填充默認(rèn)值。

error_content_type?

指定發(fā)送給客戶(hù)端的錯(cuò)誤響應(yīng)的 Content-Type HTTP 標(biāo)頭。 默認(rèn)值為 'text/html'

protocol_version?

Specifies the HTTP version to which the server is conformant. It is sent in responses to let the client know the server's communication capabilities for future requests. If set to 'HTTP/1.1', the server will permit HTTP persistent connections; however, your server must then include an accurate Content-Length header (using send_header()) in all of its responses to clients. For backwards compatibility, the setting defaults to 'HTTP/1.0'.

MessageClass?

指定一個(gè) email.message.Message 這樣的類(lèi)來(lái)解析 HTTP 標(biāo)頭。 通常該屬性不會(huì)被重載,其默認(rèn)值為 http.client.HTTPMessage。

responses?

該屬性包含一個(gè)整數(shù)錯(cuò)誤代碼與由短消息和長(zhǎng)消息組成的二元組的映射。 例如,{code: (shortmessage, longmessage)}。 shortmessage 通常是作為消息響應(yīng)中的 message 鍵,而 longmessage 則是作為 explain 鍵。 該屬性會(huì)被 send_response_only()send_error() 方法所使用。

BaseHTTPRequestHandler 實(shí)例具有下列方法:

handle()?

調(diào)用 handle_one_request() 一次(或者如果啟用了永久連接則為多次)來(lái)處理傳入的 HTTP 請(qǐng)求。 你應(yīng)該完全不需要重載它;而是要實(shí)現(xiàn)適當(dāng)?shù)?do_*() 方法。

handle_one_request()?

此方法將解析并將請(qǐng)求分配給適當(dāng)?shù)?do_*() 方法。 你應(yīng)該完全不需要重載它。

handle_expect_100()?

When an HTTP/1.1 conformant server receives an Expect: 100-continue request header it responds back with a 100 Continue followed by 200 OK headers. This method can be overridden to raise an error if the server does not want the client to continue. For e.g. server can choose to send 417 Expectation Failed as a response header and return False.

3.2 新版功能.

send_error(code, message=None, explain=None)?

發(fā)送并記錄回復(fù)給客戶(hù)端的完整錯(cuò)誤信息。 數(shù)字形式的 code 指明 HTTP 錯(cuò)誤代碼,可選的 message 為簡(jiǎn)短的易于人類(lèi)閱讀的錯(cuò)誤描述。 explain 參數(shù)可被用于提供更詳細(xì)的錯(cuò)誤信息;它將使用 error_message_format 屬性來(lái)進(jìn)行格式化并在一組完整的標(biāo)頭之后作為響應(yīng)體被發(fā)送。 responses 屬性存放了 messageexplain 的默認(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ū)并記錄被接受的請(qǐng)求。 HTTP 響應(yīng)行會(huì)被寫(xiě)入到內(nèi)部緩沖區(qū),后面是 ServerDate 標(biāo)頭。 這兩個(gè)標(biāo)頭的值將分別通過(guò) 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í)寫(xiě)入輸出流。 keyword 應(yīng)當(dāng)指定標(biāo)頭關(guān)鍵字,并以 value 指定其值。 請(qǐng)注意,在 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ā)送給客戶(hù)端的場(chǎng)合。 標(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ì)被寫(xiě)入到輸出流。

flush_headers()?

最終將標(biāo)頭發(fā)送到輸出流并清空內(nèi)部標(biāo)頭緩沖區(qū)。

3.3 新版功能.

log_request(code='-', size='-')?

記錄一次被接受(成功)的請(qǐng)求。 code 應(yīng)當(dāng)指定與請(qǐng)求相關(guān)聯(lián)的 HTTP 代碼。 如果請(qǐng)求的大小可用,則它應(yīng)當(dāng)作為 size 形參傳入。

log_error(...)?

當(dāng)請(qǐng)求無(wú)法完成時(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ù)用作格式化操作的輸入。 每條消息日志記錄的開(kāi)頭都會(huì)加上客戶(hù)端 IP 地址和當(dāng)前日期時(shí)間。

version_string()?

返回服務(wù)器軟件的版本字符串。 該值為 server_versionsys_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é)果看起來(lái)像 'Sun, 06 Nov 1994 08:49:37 GMT'

log_date_time_string()?

返回當(dāng)前的日期和時(shí)間,為日志格式化

address_string()?

返回客戶(hù)端的地址

在 3.3 版更改: 在之前版本中,會(huì)執(zhí)行一次名稱(chēng)查找。 為了避免名稱(chēng)解析的時(shí)延,現(xiàn)在將總是返回 IP 地址。

class http.server.SimpleHTTPRequestHandler(request, client_address, server, directory=None)?

這個(gè)類(lèi)會(huì)為目錄 directory 及以下的文件提供發(fā)布服務(wù),或者如果未提供 directory 則為當(dāng)前目錄,直接將目錄結(jié)構(gòu)映射到 HTTP 請(qǐng)求。

3.7 新版功能: directory 形參。

在 3.9 版更改: directory 形參接受一個(gè) path-like object。

諸如解析請(qǐng)求之類(lèi)的大量工作都是由基類(lèi) BaseHTTPRequestHandler 完成的。本類(lèi)實(shí)現(xiàn)了 do_GET()do_HEAD() 函數(shù)。

以下是 SimpleHTTPRequestHandler 的類(lèi)屬性。

server_version?

這會(huì)是 "SimpleHTTP/" + __version__,其中 __version__ 定義于模塊級(jí)別。

extensions_map?

將后綴映射為 MIME 類(lèi)型的字典,其中包含了覆蓋系統(tǒng)默認(rèn)值的自定義映射關(guān)系。不區(qū)分大小寫(xiě),因此字典鍵只應(yīng)為小寫(xiě)值。

在 3.9 版更改: 此字典不再填充默認(rèn)的系統(tǒng)映射,而只包含覆蓋值。

SimpleHTTPRequestHandler 類(lèi)定義了以下方法:

do_HEAD()?

本方法為 'HEAD' 請(qǐng)求提供服務(wù):它將發(fā)送等同于 GET 請(qǐng)求的頭文件。關(guān)于合法頭部信息的更完整解釋?zhuān)?qǐng)參閱 do_GET() 方法。

do_GET()?

通過(guò)將請(qǐng)求解釋為相對(duì)于當(dāng)前工作目錄的路徑,將請(qǐng)求映射到某個(gè)本地文件。

如果請(qǐng)求被映射到目錄,則會(huì)依次檢查該目錄是否存在 index.htmlindex.htm 文件。若存在則返回文件內(nèi)容;否則會(huì)調(diào)用 list_directory() 方法生成目錄列表。本方法將利用 os.listdir() 掃描目錄,如果 listdir() 失敗,則返回 404 出錯(cuò)應(yīng)答。

如果請(qǐng)求被映射到文件,則會(huì)打開(kāi)該文件。 打開(kāi)文件時(shí)的任何 OSError 異常都會(huì)被映射為 404, 'File not found' 錯(cuò)誤。 如果請(qǐng)求中帶有 'If-Modified-Since' 標(biāo)頭,而在此時(shí)間點(diǎn)之后文件未作修改,則會(huì)發(fā)送 304, 'Not Modified' 的響應(yīng)。 否則會(huì)調(diào)用 guess_type() 方法猜測(cè)內(nèi)容的類(lèi)型,該方法會(huì)反過(guò)來(lái)用到 extensions_map 變量,并返回文件內(nèi)容。

將會(huì)輸出 'Content-type:' 頭部信息,帶上猜出的內(nèi)容類(lèi)型,然后是 'Content-Length:' 頭部信息,帶有文件的大小,以及 'Last-Modified:' 頭部信息,帶有文件的修改時(shí)間。

后面是一個(gè)空行,標(biāo)志著頭部信息的結(jié)束,然后輸出文件的內(nèi)容。如果文件的 MIME 類(lèi)型以 text/ 開(kāi)頭,文件將以文本模式打開(kāi);否則將使用二進(jìn)制模式。

用法示例請(qǐng)參閱 http.server 模塊中的 test() 函數(shù)的實(shí)現(xiàn)。

在 3.7 版更改: 'If-Modified-Since' 頭部信息提供支持。

SimpleHTTPRequestHandler 類(lèi)的用法可如下所示,以便創(chuàng)建一個(gè)非常簡(jiǎn)單的 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 can also be invoked directly using the -m switch of the interpreter. Similar to the previous example, this serves files relative to the current directory:

python -m http.server

The server listens to port 8000 by default. The default can be overridden by passing the desired port number as an argument:

python -m http.server 9000

By default, the server binds itself to all interfaces. The option -b/--bind specifies a specific address to which it should bind. Both IPv4 and IPv6 addresses are supported. For example, the following command causes the server to bind to localhost only:

python -m http.server --bind 127.0.0.1

3.4 新版功能: 引入了 --bind 參數(shù)。

3.8 新版功能: 為了支持 IPv6 改進(jìn)了 --bind 參數(shù)。

By default, the server uses the current directory. The option -d/--directory specifies a directory to which it should serve the files. For example, the following command uses a specific directory:

python -m http.server --directory /tmp/

3.7 新版功能: --directory argument was introduced.

By default, the server is conformant to HTTP/1.0. The option -p/--protocol specifies the HTTP version to which the server is conformant. For example, the following command runs an HTTP/1.1 conformant server:

python -m http.server --protocol HTTP/1.1

3.11 新版功能: --protocol argument was introduced.

class http.server.CGIHTTPRequestHandler(request, client_address, server)?

該類(lèi)可為當(dāng)前及以下目錄中的文件或輸出 CGI 腳本提供服務(wù)。注意,把 HTTP 分層結(jié)構(gòu)映射到本地目錄結(jié)構(gòu),這與 SimpleHTTPRequestHandler 完全一樣。

備注

CGIHTTPRequestHandler 類(lèi)運(yùn)行的 CGI 腳本不能進(jìn)行重定向操作(HTTP 代碼302),因?yàn)樵趫?zhí)行 CGI 腳本之前會(huì)發(fā)送代碼 200(接下來(lái)就輸出腳本)。這樣狀態(tài)碼就沖突了。

然而,如果這個(gè)類(lèi)猜測(cè)它是一個(gè) CGI 腳本,那么就會(huì)運(yùn)行該 CGI 腳本,而不是作為文件提供出去。 只會(huì)識(shí)別基于目錄的 CGI —— 另有一種常用的服務(wù)器設(shè)置,即標(biāo)識(shí) CGI 腳本是通過(guò)特殊的擴(kuò)展名。

如果請(qǐng)求指向 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' 請(qǐng)求,僅用于 CGI 腳本。如果試圖向非 CGI 網(wǎng)址發(fā)送 POST 請(qǐng)求,則會(huì)輸出錯(cuò)誤 501:Can only POST to CGI scripts"。

請(qǐng)注意,為了保證安全性,CGI 腳本將以用戶(hù) nobody 的 UID 運(yùn)行。CGI 腳本運(yùn)行錯(cuò)誤將被轉(zhuǎn)換為錯(cuò)誤 403。

通過(guò)在命令行傳入 --cgi 參數(shù),可以啟用 CGIHTTPRequestHandler

python -m http.server --cgi