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

源代碼: Lib/http/server.py


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

警告

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

HTTPServersocketserver.TCPServer 的一個子類。它會創(chuàng)建和偵聽 HTTP 套接字,并將請求分發(fā)給處理程序。創(chuàng)建和運行 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 類,并在實例變量 server_nameserver_port 中保存 HTTP 服務(wù)器地址。處理程序可通過實例變量 server 訪問 HTTP 服務(wù)器。

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

該類相似于 HTTPServer ,只是會利用 ThreadingMixIn 對請求進行多線程處理。當需要對 Web 瀏覽器預(yù)先打開套接字進行處理時,這就很有用,這時 HTTPServer 會一直等待請求。

3.7 新版功能.

實例化 HTTPServerThreadingHTTPServer 時,必須給出一個 RequestHandlerClass,本模塊提供了該對象的三種變體:

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

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

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

BaseHTTPRequestHandler 具有下列實例變量:

client_address?

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

server?

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

close_connection?

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

requestline?

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

command?

包含具體的命令(請求類型)。 例如 'GET'。

path?

包含請求路徑。如果URL的查詢部分存在, path 會包含這個查詢部分。使用 RFC 3986 的術(shù)語來說,在這里, path 包含 hier-partquery 。

request_version?

包含請求的版本字符串。 例如 'HTTP/1.0'。

headers?

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

rfile?

一個 io.BufferedIOBase 輸入流,準備從可選的輸入數(shù)據(jù)的開頭進行讀取。

wfile?

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

在 3.6 版更改: 這是一個 io.BufferedIOBase 流。

BaseHTTPRequestHandler 具有下列屬性:

server_version?

指定服務(wù)器軟件版本。 你可能會想要重載該屬性。 該屬性的格式為多個以空格分隔的字符串,其中每個字符串的形式為 name[/version]。 例如 'BaseHTTP/0.2'

sys_version?

包含 Python 系統(tǒng)版本,采用 version_string 方法和 server_version 類變量所支持的形式。 例如 'Python/1.4'

error_message_format?

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

error_content_type?

指定發(fā)送給客戶端的錯誤響應(yīng)的 Content-Type HTTP 標頭。 默認值為 '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?

指定一個 email.message.Message 這樣的類來解析 HTTP 標頭。 通常該屬性不會被重載,其默認值為 http.client.HTTPMessage。

responses?

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

BaseHTTPRequestHandler 實例具有下列方法:

handle()?

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

handle_one_request()?

此方法將解析并將請求分配給適當?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ù)給客戶端的完整錯誤信息。 數(shù)字形式的 code 指明 HTTP 錯誤代碼,可選的 message 為簡短的易于人類閱讀的錯誤描述。 explain 參數(shù)可被用于提供更詳細的錯誤信息;它將使用 error_message_format 屬性來進行格式化并在一組完整的標頭之后作為響應(yīng)體被發(fā)送。 responses 屬性存放了 messageexplain 的默認值,它們將在未提供時被使用;對于未知代碼兩者的默認值均為字符串 ???。 如果方法為 HEAD 或響應(yīng)代碼是下列值之一則響應(yīng)體將為空: 1xx, 204 No Content, 205 Reset Content, 304 Not Modified。

在 3.4 版更改: 錯誤響應(yīng)包括一個 Content-Length 標頭。 增加了 explain 參數(shù)。

send_response(code, message=None)?

將一個響應(yīng)標頭添加到標頭緩沖區(qū)并記錄被接受的請求。 HTTP 響應(yīng)行會被寫入到內(nèi)部緩沖區(qū),后面是 ServerDate 標頭。 這兩個標頭的值將分別通過 version_string()date_time_string() 方法獲取。 如果服務(wù)器不打算使用 send_header() 方法發(fā)送任何其他標頭,則 send_response() 后面應(yīng)該跟一個 end_headers() 調(diào)用。

在 3.3 版更改: 標頭會被存儲到內(nèi)部緩沖區(qū)并且需要顯式地調(diào)用 end_headers()

send_header(keyword, value)?

將 HTTP 標頭添加到內(nèi)部緩沖區(qū),它將在 end_headers()flush_headers() 被發(fā)起調(diào)用時寫入輸出流。 keyword 應(yīng)當指定標頭關(guān)鍵字,并以 value 指定其值。 請注意,在 send_header 調(diào)用結(jié)束之后,必須調(diào)用 end_headers() 以便完成操作。

在 3.2 版更改: 標頭將被存入內(nèi)部緩沖區(qū)。

send_response_only(code, message=None)?

只發(fā)送響應(yīng)標頭,用于當 100 Continue 響應(yīng)被服務(wù)器發(fā)送給客戶端的場合。 標頭不會被緩沖而是直接發(fā)送到輸出流。 如果未指定 message,則會發(fā)送與響應(yīng) code 相對應(yīng)的 HTTP 消息。

3.2 新版功能.

end_headers()?

將一個空行(指明響應(yīng)中 HTTP 標頭的結(jié)束)添加到標頭緩沖區(qū)并調(diào)用 flush_headers()。

在 3.2 版更改: 已緩沖的標頭會被寫入到輸出流。

flush_headers()?

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

3.3 新版功能.

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

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

log_error(...)?

當請求無法完成時記錄一次錯誤。 默認情況下,它會將消息傳給 log_message(),因此它接受同樣的參數(shù) (format 和一些額外的值)。

log_message(format, ...)?

將任意一條消息記錄到 sys.stderr。 此方法通常會被重載以創(chuàng)建自定義的錯誤日志記錄機制。 format 參數(shù)是標準 printf 風(fēng)格的格式字符串,其中會將傳給 log_message() 的額外參數(shù)用作格式化操作的輸入。 每條消息日志記錄的開頭都會加上客戶端 IP 地址和當前日期時間。

version_string()?

返回服務(wù)器軟件的版本字符串。 該值為 server_versionsys_version 屬性的組合。

date_time_string(timestamp=None)?

返回由 timestamp 所給定的日期和時間(參數(shù)應(yīng)為 None 或為 time.time() 所返回的格式),格式化為一個消息標頭。 如果省略 timestamp,則會使用當前日期和時間。

結(jié)果看起來像 'Sun, 06 Nov 1994 08:49:37 GMT'。

log_date_time_string()?

返回當前的日期和時間,為日志格式化

address_string()?

返回客戶端的地址

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

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

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

3.7 新版功能: directory 形參。

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

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

以下是 SimpleHTTPRequestHandler 的類屬性。

server_version?

這會是 "SimpleHTTP/" + __version__,其中 __version__ 定義于模塊級別。

extensions_map?

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

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

SimpleHTTPRequestHandler 類定義了以下方法:

do_HEAD()?

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

do_GET()?

通過將請求解釋為相對于當前工作目錄的路徑,將請求映射到某個本地文件。

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

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

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

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

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

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

SimpleHTTPRequestHandler 類的用法可如下所示,以便創(chuàng)建一個非常簡單的 Web 服務(wù),為相對于當前目錄的文件提供服務(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 改進了 --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)?

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

備注

CGIHTTPRequestHandler 類運行的 CGI 腳本不能進行重定向操作(HTTP 代碼302),因為在執(zhí)行 CGI 腳本之前會發(fā)送代碼 200(接下來就輸出腳本)。這樣狀態(tài)碼就沖突了。

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

如果請求指向 cgi_directories 以下的路徑,do_GET()do_HEAD() 函數(shù)已作修改,不是給出文件,而是運行 CGI 腳本并輸出結(jié)果。

CGIHTTPRequestHandler 定義了以下數(shù)據(jù)成員:

cgi_directories?

默認為 ['/cgi-bin', '/htbin'],視作 CGI 腳本所在目錄。

CGIHTTPRequestHandler 定義了以下方法:

do_POST()?

本方法服務(wù)于 'POST' 請求,僅用于 CGI 腳本。如果試圖向非 CGI 網(wǎng)址發(fā)送 POST 請求,則會輸出錯誤 501:Can only POST to CGI scripts"。

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

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

python -m http.server --cgi