http.server — HTTP 伺服器

原始碼: Lib/http/server.py


此模組定義了用於實現 HTTP 伺服器的類。

警告

不建議在生產環境中使用http.server。它僅實現基本安全檢查

可用性: 不適用於 WASI。

此模組在 WebAssembly 上不起作用或不可用。 有關更多資訊,請參閱 WebAssembly 平臺

其中一個類 HTTPServersocketserver.TCPServer 的子類。它建立並監聽 HTTP 套接字,並將請求分派給處理程式。 建立並執行伺服器的程式碼如下所示:

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)

此類透過將伺服器地址儲存為名為 server_nameserver_port 的例項變數來構建 TCPServer 類。 處理程式可以訪問伺服器,通常透過處理程式的 server 例項變數。

class http.server.ThreadingHTTPServer(server_address, RequestHandlerClass)

此類與 HTTPServer 相同,但使用執行緒透過 ThreadingMixIn 來處理請求。這對於處理 Web 瀏覽器預先開啟的套接字很有用,在這些套接字上 HTTPServer 會無限期地等待。

3.7 版本新增。

HTTPServerThreadingHTTPServer 必須在例項化時給定一個 RequestHandlerClass,此模組提供了三個不同的變體:

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

此類用於處理到達伺服器的 HTTP 請求。 它本身無法響應任何實際的 HTTP 請求; 必須對其進行子類化才能處理每個請求方法(例如,GET 或 POST)。 BaseHTTPRequestHandler 提供了許多類和例項變數以及供子類使用的方法。

處理程式將解析請求和標頭,然後呼叫特定於請求型別的方法。 方法名稱是從請求構造的。 例如,對於請求方法 SPAM,將呼叫 do_SPAM() 方法,且不帶任何引數。 所有相關資訊都儲存在處理程式的例項變數中。 子類不應需要重寫或擴充套件 __init__() 方法。

BaseHTTPRequestHandler 具有以下例項變數

client_address

包含 (host, port) 形式的元組,該元組引用客戶端的地址。

server

包含伺服器例項。

close_connection

布林值,應在 handle_one_request() 返回之前設定,指示是否可以期望另一個請求,或者是否應關閉連線。

requestline

包含 HTTP 請求行的字串表示形式。 將刪除結尾的 CRLF。 此屬性應由 handle_one_request() 設定。 如果沒有處理有效的請求行,則應將其設定為空字串。

command

包含命令(請求型別)。 例如,'GET'

path

包含請求路徑。 如果存在 URL 的查詢元件,則 path 包括查詢。 使用 RFC 3986 的術語,此處的 path 包括 hier-partquery

request_version

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

headers

儲存由 MessageClass 類變數指定的類的例項。 此例項分析和管理 HTTP 請求中的標頭。parse_headers() 函式來自 http.client,用於解析標頭,並且它要求 HTTP 請求提供有效的 RFC 2822 樣式的標頭。

rfile

一個 io.BufferedIOBase 輸入流,準備好從可選的輸入資料開始讀取。

wfile

包含用於將響應寫回客戶端的輸出流。 為了實現與 HTTP 客戶端的成功互操作,在寫入此流時必須正確遵守 HTTP 協議。

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

BaseHTTPRequestHandler 具有以下屬性

server_version

指定伺服器軟體版本。 你可能想要覆蓋它。 格式是多個以空格分隔的字串,其中每個字串的形式為 name[/version]。 例如,'BaseHTTP/0.2'

sys_version

包含 Python 系統版本,格式可供 version_string 方法和 server_version 類變數使用。 例如,'Python/1.4'

error_message_format

指定 send_error() 方法用於構建對客戶端的錯誤響應的格式字串。 該字串預設使用來自 responses 的變數填充,這些變數基於傳遞給 send_error() 的狀態程式碼。

error_content_type

指定傳送到客戶端的錯誤響應的 Content-Type HTTP 標頭。 預設值為 'text/html'

protocol_version

指定伺服器符合的 HTTP 版本。 它在響應中傳送,以讓客戶端知道伺服器未來請求的通訊能力。 如果設定為 'HTTP/1.1',則伺服器將允許 HTTP 持久連線;但是,您的伺服器 *必須* 在其所有對客戶端的響應中包含準確的 Content-Length 標頭(使用 send_header())。 為了向後相容,該設定預設為 'HTTP/1.0'

MessageClass

指定一個類似於 email.message.Message 的類來解析 HTTP 標頭。 通常,這不會被覆蓋,並且它預設為 http.client.HTTPMessage

responses

此屬性包含錯誤程式碼整數到包含簡短和長訊息的二元組的對映。 例如,{code: (shortmessage, longmessage)}。 *shortmessage* 通常用作錯誤響應中的 *message* 鍵,*longmessage* 用作 *explain* 鍵。 它被 send_response_only()send_error() 方法使用。

BaseHTTPRequestHandler 例項具有以下方法

handle()

呼叫 handle_one_request() 一次(或者,如果啟用了持久連線,則多次)來處理傳入的 HTTP 請求。 你永遠不需要覆蓋它;相反,實現適當的 do_*() 方法。

handle_one_request()

此方法將解析請求並將其分派到適當的 do_*() 方法。 你永遠不需要覆蓋它。

handle_expect_100()

當符合 HTTP/1.1 的伺服器收到 Expect: 100-continue 請求標頭時,它會返回 100 Continue,後跟 200 OK 標頭。 如果伺服器不希望客戶端繼續,則可以覆蓋此方法以引發錯誤。 例如,伺服器可以選擇傳送 417 Expectation Failed 作為響應標頭,並 return False

在 3.2 版本中新增。

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

傳送並記錄對客戶端的完整錯誤回覆。 數字 *code* 指定 HTTP 錯誤程式碼,*message* 作為錯誤的可選、簡短、人類可讀描述。 *explain* 引數可用於提供有關錯誤的更多詳細資訊;它將使用 error_message_format 屬性進行格式化,並在完整的一組標頭之後,作為響應正文發出。 如果沒有提供值,responses 屬性儲存 *message* 和 *explain* 的預設值;對於未知程式碼,兩者的預設值都是字串 ???。 如果該方法是 HEAD 或響應程式碼是以下之一,則正文將為空:1xx204 No Content205 Reset Content304 Not Modified

3.4 版本更改: 錯誤響應包括 Content-Length 標頭。 添加了 *explain* 引數。

send_response(code, message=None)

將響應標頭新增到標頭緩衝區並記錄接受的請求。 HTTP 響應行被寫入內部緩衝區,後跟 *Server* 和 *Date* 標頭。 這兩個標頭的值分別從 version_string()date_time_string() 方法中獲取。 如果伺服器不打算使用 send_header() 方法傳送任何其他標頭,那麼 send_response() 應該後跟 end_headers() 呼叫。

3.3 版本更改: 標頭儲存到內部緩衝區,並且需要顯式呼叫 end_headers()

send_header(keyword, value)

將 HTTP 標頭新增到內部緩衝區,該緩衝區將在呼叫 end_headers()flush_headers() 時寫入輸出流。 *keyword* 應指定標頭關鍵字,*value* 指定其值。 請注意,在完成 send_header 呼叫後,*必須* 呼叫 end_headers() 才能完成操作。

3.2 版本更改: 標頭儲存在內部緩衝區中。

send_response_only(code, message=None)

僅傳送響應頭,用於伺服器向客戶端傳送 100 Continue 響應的情況。頭部資訊不會被緩衝,而是直接傳送到輸出流。如果未指定message,則會發送與響應code對應的 HTTP 訊息。

在 3.2 版本中新增。

end_headers()

在頭部緩衝區中新增一個空行(表示響應中 HTTP 頭部的結束),並呼叫 flush_headers()

在 3.2 版本中更改: 已緩衝的頭部資訊會被寫入輸出流。

flush_headers()

最終將頭部資訊傳送到輸出流並重新整理內部頭部緩衝區。

在 3.3 版本中新增。

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

記錄一個已接受(成功)的請求。code 應指定與響應關聯的數字 HTTP 程式碼。如果響應的大小可用,則應將其作為 size 引數傳遞。

log_error(...)

記錄無法滿足請求時出現的錯誤。預設情況下,它將訊息傳遞給 log_message(),因此它接受相同的引數(format 和附加值)。

log_message(format, ...)

將任意訊息記錄到 sys.stderr。通常會重寫此方法以建立自定義的錯誤記錄機制。format 引數是一個標準的 printf 樣式格式字串,其中將 log_message() 的其他引數應用為格式化的輸入。客戶端 IP 地址以及當前日期和時間會新增到每個記錄的訊息的前面。

version_string()

返回伺服器軟體的版本字串。這是 server_versionsys_version 屬性的組合。

date_time_string(timestamp=None)

返回由 timestamp 給定的日期和時間(必須為 Nonetime.time() 返回的格式),格式化為訊息頭。如果省略 timestamp,則使用當前日期和時間。

結果看起來像 'Sun, 06 Nov 1994 08:49:37 GMT'

log_date_time_string()

返回當前的日期和時間,格式化為日誌記錄。

address_string()

返回客戶端地址。

在 3.3 版本中更改: 之前,執行了名稱查詢。為避免名稱解析延遲,現在始終返回 IP 地址。

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

此類從 directory 及其子目錄中提供檔案,如果未提供 directory,則從當前目錄提供檔案,直接將目錄結構對映到 HTTP 請求。

在 3.7 版本中更改: 添加了 directory 引數。

在 3.9 版本中更改: directory 引數接受 類路徑物件

許多工作,例如解析請求,由基類 BaseHTTPRequestHandler 完成。此類實現了 do_GET()do_HEAD() 函式。

以下定義為 SimpleHTTPRequestHandler 的類級別屬性

server_version

這將是 "SimpleHTTP/" + __version__,其中 __version__ 在模組級別定義。

extensions_map

一個將字尾對映到 MIME 型別的字典,包含預設系統對映的自定義覆蓋。對映不區分大小寫,因此應僅包含小寫鍵。

在 3.9 版本中更改: 此字典不再填充預設系統對映,而僅包含覆蓋。

SimpleHTTPRequestHandler 類定義了以下方法

do_HEAD()

此方法服務於 'HEAD' 請求型別:它傳送與等效 GET 請求相同的頭部。有關可能的頭部的更完整說明,請參見 do_GET() 方法。

do_GET()

透過將請求解釋為相對於當前工作目錄的路徑,將請求對映到本地檔案。

如果請求對映到一個目錄,則會檢查該目錄中是否存在名為 index.htmlindex.htm (按此順序)的檔案。如果找到,則返回該檔案的內容;否則,透過呼叫 list_directory() 方法生成目錄列表。此方法使用 os.listdir() 掃描目錄,如果 listdir() 失敗,則返回 404 錯誤響應。

如果請求被對映到一個檔案,則該檔案會被開啟。任何在開啟請求檔案時發生的 OSError 異常都會被對映為 404'File not found' 錯誤。如果請求中存在 'If-Modified-Since' 標頭,並且檔案在此時間後未被修改,則會發送 304'Not Modified' 響應。否則,透過呼叫 guess_type() 方法來猜測內容型別,該方法會使用 extensions_map 變數,然後返回檔案內容。

輸出一個帶有猜測內容型別的 'Content-type:' 標頭,後跟一個帶有檔案大小的 'Content-Length:' 標頭和一個帶有檔案修改時間的 'Last-Modified:' 標頭。

接下來是一個空行,表示標頭的結束,然後輸出檔案內容。如果檔案的 MIME 型別以 text/ 開頭,則以文字模式開啟檔案;否則使用二進位制模式。

有關用法示例,請參閱 Lib/http/server.pytest 函式的實現。

3.7 版本更改: 支援 'If-Modified-Since' 標頭。

SimpleHTTPRequestHandler 類可以透過以下方式使用,以建立一個非常基本的 Web 伺服器,該伺服器提供相對於當前目錄的檔案:

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

SimpleHTTPRequestHandler 也可以被子類化以增強行為,例如透過覆蓋類屬性 index_pages 來使用不同的索引檔名。

也可以使用直譯器的 -m 開關直接呼叫 http.server。與前面的示例類似,這會提供相對於當前目錄的檔案:

python -m http.server

預設情況下,伺服器偵聽 8000 埠。可以透過傳遞所需的埠號作為引數來覆蓋預設值:

python -m http.server 9000

預設情況下,伺服器會繫結到所有介面。選項 -b/--bind 指定它應繫結到的特定地址。支援 IPv4 和 IPv6 地址。例如,以下命令使伺服器僅繫結到 localhost:

python -m http.server --bind 127.0.0.1

3.4 版本更改: 添加了 --bind 選項。

3.8 版本更改: --bind 選項中支援 IPv6。

預設情況下,伺服器使用當前目錄。選項 -d/--directory 指定它應提供檔案的目錄。例如,以下命令使用特定目錄:

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

3.7 版本更改: 添加了 --directory 選項。

預設情況下,伺服器符合 HTTP/1.0。選項 -p/--protocol 指定伺服器符合的 HTTP 版本。例如,以下命令執行符合 HTTP/1.1 的伺服器:

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

3.11 版本更改: 添加了 --protocol 選項。

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

此類用於提供當前目錄及其下方的檔案或 CGI 指令碼的輸出。請注意,HTTP 分層結構到本地目錄結構的對映與 SimpleHTTPRequestHandler 中的完全相同。

注意

CGIHTTPRequestHandler 類執行的 CGI 指令碼無法執行重定向(HTTP 程式碼 302),因為程式碼 200(指令碼輸出如下)在執行 CGI 指令碼之前傳送。這會搶佔狀態碼。

但是,如果該類猜測它是 CGI 指令碼,則會執行 CGI 指令碼,而不是將其作為檔案提供。僅使用基於目錄的 CGI — 其他常見的伺服器配置是將特殊副檔名視為表示 CGI 指令碼。

如果請求指向 cgi_directories 路徑下的某個位置,則修改 do_GET()do_HEAD() 函式以執行 CGI 指令碼並提供輸出,而不是提供檔案。

CGIHTTPRequestHandler 定義以下資料成員:

cgi_directories

此預設值為 ['/cgi-bin', '/htbin'],並描述要視為包含 CGI 指令碼的目錄。

CGIHTTPRequestHandler 定義以下方法:

do_POST()

此方法提供 'POST' 請求型別,僅允許用於 CGI 指令碼。當嘗試向非 CGI URL 傳送 POST 請求時,會輸出錯誤 501,“只能向 CGI 指令碼傳送 POST 請求”。

請注意,出於安全原因,CGI 指令碼將以使用者 nobody 的 UID 執行。CGI 指令碼的問題將轉換為錯誤 403。

3.13 版本已棄用,將在 3.15 版本中移除: CGIHTTPRequestHandler 將在 3.15 中移除。CGI 已被認為是不好的處理方式,已經超過十年了。此程式碼已經有一段時間沒有維護,並且很少在實際中使用。保留它可能會導致進一步的 安全考慮

可以透過傳遞 --cgi 選項在命令列中啟用 CGIHTTPRequestHandler

python -m http.server --cgi

3.13 版本已棄用,將在 3.15 版本中移除: http.server 命令列 --cgi 支援將被刪除,因為 CGIHTTPRequestHandler 將被刪除。

警告

CGIHTTPRequestHandler--cgi 命令列選項不適合不受信任的客戶端使用,並且可能容易受到利用。始終在安全環境中使用。

安全注意事項

在處理請求時,SimpleHTTPRequestHandler 將遵循符號連結,這使得可以提供指定目錄之外的檔案。

Python 的早期版本不會從 python -m http.server 或預設的 BaseHTTPRequestHandler .log_message 實現發出的 stderr 日誌訊息中清除控制字元。這可能允許連線到您的伺服器的遠端客戶端將惡意控制程式碼傳送到您的終端。

3.12 版本更改: 在 stderr 日誌中清除了控制字元。