http.server --- HTTP 服務(wù)器?
源代碼: Lib/http/server.py
這個模塊定義了實現(xiàn) HTTP 服務(wù)器( Web 服務(wù)器)的類。
警告
不推薦在生產(chǎn)環(huán)境中使用 http.server 。它只實現(xiàn)了基本的安全檢查功能。
HTTPServer 是 socketserver.TCPServer 的一個子類。它會創(chuàng)建和偵聽 HTTP 套接字,并將請求調(diào)度給處理程序。用于創(chuàng)建和運行服務(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類,并會將服務(wù)器地址存入名為server_name和server_port的實例變量中。服務(wù)器可被處理程序通過server實例變量訪問。
-
class
http.server.ThreadingHTTPServer(server_address, RequestHandlerClass)? 這個類與 HTTPServer 相似,但會通過使用
ThreadingMixIn來以線程處理請求。 這適用于處理 Web 瀏覽器預(yù)開啟套接字,以便HTTPServer無限期地執(zhí)行等待。3.7 新版功能.
HTTPServer 和 ThreadingHTTPServer 必須在實例化時給定一個 RequestHandlerClass,此模塊提供了該對象的三種不同形式:
-
class
http.server.BaseHTTPRequestHandler(request, client_address, server)? 這個類用于處理到達服務(wù)器的 HTTP 請求。 它本身無法響應(yīng)任何實際的 HTTP 請求;它必須被子類化以處理每個請求方法(例如 GET 或 POST)。
BaseHTTPRequestHandler提供了許多供子類使用的類和實例變量以及方法。這個處理程序?qū)⒔馕稣埱蠛蜆?biāo)頭,然后調(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)當(dāng)在
handle_one_request()返回之前設(shè)定的布爾值,指明是否要期待另一個請求,還是應(yīng)當(dāng)關(guān)閉連接。
-
requestline? 包含 HTTP 請求行的字符串表示。 末尾的 CRLF 會被去除。 該屬性應(yīng)當(dāng)由
handle_one_request()來設(shè)定。 如果無有效請求行被處理,則它應(yīng)當(dāng)被設(shè)為空字符串。
-
command? 包含具體的命令(請求類型)。 例如
'GET'。
-
path? 包含請求路徑。
-
request_version? 包含請求的版本字符串。 例如
'HTTP/1.0'。
-
headers? 存放由
MessageClass類變量所指定的類的實例。 該實例會解析并管理 HTTP 請求中的標(biāo)頭。http.client中的parse_headers()函數(shù)將被用來解析標(biāo)頭并且它需要 HTTP 請求提供一個有效的 RFC 2822 風(fēng)格的標(biāo)頭。
-
rfile? 一個
io.BufferedIOBase輸入流,準(zhǔn)備從可選的輸入數(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)當(dāng)被
send_error()方法用來構(gòu)建發(fā)給客戶端的錯誤響應(yīng)的格式字符串。 該字符串應(yīng)使用來自responses的變量根據(jù)傳給send_error()的狀態(tài)碼來填充默認(rèn)值。
-
error_content_type? 指定發(fā)送給客戶端的錯誤響應(yīng)的 Content-Type HTTP 標(biāo)頭。 默認(rèn)值為
'text/html'。
-
protocol_version? 該屬性指定在響應(yīng)中使用的 HTTP 協(xié)議版本。 如果設(shè)為
'HTTP/1.1',服務(wù)器將允許 HTTP 永久連接;但是,這樣你的服務(wù)器 必須 在發(fā)給客戶端的所有響應(yīng)中包括一個準(zhǔn)確的Content-Length標(biāo)頭 (使用send_header())。 為了向下兼容,該設(shè)置默認(rèn)為'HTTP/1.0'。
-
MessageClass? 指定一個
email.message.Message這樣的類來解析 HTTP 標(biāo)頭。 通常該屬性不會被重載,其默認(rèn)值為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)適當(dāng)?shù)?do_*()方法。
-
handle_one_request()? 此方法將解析并將請求分配給適當(dāng)?shù)?
do_*()方法。 你應(yīng)該完全不需要重載它。
-
handle_expect_100()? When a HTTP/1.1 compliant server receives an
Expect: 100-continuerequest header it responds back with a100 Continuefollowed by200 OKheaders. This method can be overridden to raise an error if the server does not want the client to continue. For e.g. server can chose to send417 Expectation Failedas a response header andreturn False.3.2 新版功能.
-
send_error(code, message=None, explain=None)? 發(fā)送并記錄回復(fù)給客戶端的完整錯誤信息。 數(shù)字形式的 code 指明 HTTP 錯誤代碼,可選的 message 為簡短的易于人類閱讀的錯誤描述。 explain 參數(shù)可被用于提供更詳細(xì)的錯誤信息;它將使用
error_message_format屬性來進行格式化并在一組完整的標(biāo)頭之后作為響應(yīng)體被發(fā)送。responses屬性存放了 message 和 explain 的默認(rèn)值,它們將在未提供時被使用;對于未知代碼兩者的默認(rèn)值均為字符串???。 如果方法為 HEAD 或響應(yīng)代碼是下列值之一則響應(yīng)體將為空:1xx,204 No Content,205 Reset Content,304 Not Modified。在 3.4 版更改: 錯誤響應(yīng)包括一個 Content-Length 標(biāo)頭。 增加了 explain 參數(shù)。
-
send_response(code, message=None)? 將一個響應(yīng)標(biāo)頭添加到標(biāo)頭緩沖區(qū)并記錄被接受的請求。 HTTP 響應(yīng)行會被寫入到內(nèi)部緩沖區(qū),后面是 Server 和 Date 標(biāo)頭。 這兩個標(biāo)頭的值將分別通過
version_string()和date_time_string()方法獲取。 如果服務(wù)器不打算使用send_header()方法發(fā)送任何其他標(biāo)頭,則send_response()后面應(yīng)該跟一個end_headers()調(diào)用。在 3.3 版更改: 標(biāo)頭會被存儲到內(nèi)部緩沖區(qū)并且需要顯式地調(diào)用
end_headers()。
-
send_header(keyword, value)? 將 HTTP 標(biāo)頭添加到內(nèi)部緩沖區(qū),它將在
end_headers()或flush_headers()被發(fā)起調(diào)用時寫入輸出流。 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)頭不會被緩沖而是直接發(fā)送到輸出流。 如果未指定 message,則會發(fā)送與響應(yīng) code 相對應(yīng)的 HTTP 消息。3.2 新版功能.
-
end_headers()? 將一個空行(指明響應(yīng)中 HTTP 標(biāo)頭的結(jié)束)添加到標(biāo)頭緩沖區(qū)并調(diào)用
flush_headers()。在 3.2 版更改: 已緩沖的標(biāo)頭會被寫入到輸出流。
-
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)請求無法完成時記錄一次錯誤。 默認(rèn)情況下,它會將消息傳給
log_message(),因此它接受同樣的參數(shù) (format 和一些額外的值)。
-
log_message(format, ...)? 將任意一條消息記錄到
sys.stderr。 此方法通常會被重載以創(chuàng)建自定義的錯誤日志記錄機制。 format 參數(shù)是標(biāo)準(zhǔn) printf 風(fēng)格的格式字符串,其中會將傳給log_message()的額外參數(shù)用作格式化操作的輸入。 每條消息日志記錄的開頭都會加上客戶端 IP 地址和當(dāng)前日期時間。
-
version_string()? 返回服務(wù)器軟件的版本字符串。 該值為
server_version與sys_version屬性的組合。
-
date_time_string(timestamp=None)? 返回由 timestamp 所給定的日期和時間(參數(shù)應(yīng)為
None或為time.time()所返回的格式),格式化為一個消息標(biāo)頭。 如果省略 timestamp,則會使用當(dāng)前日期和時間。結(jié)果看起來像
'Sun, 06 Nov 1994 08:49:37 GMT'。
-
log_date_time_string()? 返回當(dāng)前的日期和時間,為日志格式化
-
address_string()? 返回客戶端的地址
在 3.3 版更改: 在之前版本中,會執(zhí)行一次名稱查找。 為了避免名稱解析的時延,現(xiàn)在將總是返回 IP 地址。
-
-
class
http.server.SimpleHTTPRequestHandler(request, client_address, server, directory=None)? 這個類為當(dāng)前目錄及以下的文件提供服務(wù),直接映射目錄結(jié)構(gòu)到HTTP請求
諸如解析請求之類的大量工作都是由基類
BaseHTTPRequestHandler完成的。本類實現(xiàn)了do_GET()和do_HEAD()函數(shù)。以下是
SimpleHTTPRequestHandler的類屬性。-
server_version? 這會是
"SimpleHTTP/" + __version__,其中__version__定義于模塊級別。
-
extensions_map? A dictionary mapping suffixes into MIME types. The default is signified by an empty string, and is considered to be
application/octet-stream. The mapping is used case-insensitively, and so should contain only lower-cased keys.
-
directory? 如果沒有指定,要服務(wù) 目錄是當(dāng)前工作目錄
SimpleHTTPRequestHandler類定義了以下方法:-
do_GET()? 這一請求通過把其解釋為當(dāng)前工作目錄的相對路徑來映射到本地文件
如果請求被映射到目錄,則會依次檢查該目錄是否存在
index.html或index.htm文件。若存在則返回文件內(nèi)容;否則會調(diào)用list_directory()方法生成目錄列表。本方法將利用os.listdir()掃描目錄,如果listdir()失敗,則返回404出錯應(yīng)答。如果請求被映射到文件,則會打開該文件。 打開文件時的任何
OSError異常都會被映射為404,'File not found'錯誤。 如果請求中帶有'If-Modified-Since'標(biāo)頭,而在此時間點之后文件未作修改,則會發(fā)送304,'Not Modified'的響應(yīng)。 否則會調(diào)用guess_type()方法猜測內(nèi)容的類型,該方法會反過來用到 extensions_map 變量,并返回文件內(nèi)容。將會輸出
'Content-type:'頭部信息,帶上猜出的內(nèi)容類型,然后是'Content-Length:'頭部信息,帶有文件的大小,以及'Last-Modified:'頭部信息,帶有文件的修改時間。后面是一個空行,標(biāo)志著頭部信息的結(jié)束,然后輸出文件的內(nèi)容。如果文件的 MIME 類型以
text/開頭,文件將以文本模式打開;否則將使用二進制模式。用法示例請參閱
http.server模塊中的test()函數(shù)的實現(xiàn)。在 3.7 版更改: 為
'If-Modified-Since'頭部信息提供支持。
-
SimpleHTTPRequestHandler 類的用法可如下所示,以便創(chuàng)建一個非常簡單的 Web 服務(wù),為相對于當(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 開關(guān)加上 port number 參數(shù)直接發(fā)起調(diào)用。 與前面的例子類似,可支持相對于當(dāng)前目錄的文件:
python -m http.server 8000
By default, server binds itself to all interfaces. The option -b/--bind
specifies a specific address to which it should bind. For example, the
following command causes the server to bind to localhost only:
python -m http.server 8000 --bind 127.0.0.1
3.4 新版功能: 引入了 --bind 參數(shù)。
HTTP 服務(wù)器默認(rèn)使用當(dāng)前目錄。參數(shù) -d/--directory 可指定文件所在的目錄。比如以下命令就指定了一個目錄:
python -m http.server --directory /tmp/
3.7 新版功能: --directory 指定備用目錄
-
class
http.server.CGIHTTPRequestHandler(request, client_address, server)? 該類可為當(dāng)前及以下目錄中的文件或輸出 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è)置,即標(biāo)識 CGI 腳本是通過特殊的擴展名。
如果請求指向
cgi_directories以下的路徑,do_GET()和do_HEAD()函數(shù)已作修改,不是給出文件,而是運行 CGI 腳本并輸出結(jié)果。CGIHTTPRequestHandler定義了以下數(shù)據(jù)成員:-
cgi_directories? 默認(rèn)為
['/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 8000
