http.server — HTTP 伺服器

原始碼: Lib/http/server.py


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

警告

http.server 不推薦用於生產環境。它只實現了基本的安全檢查

可用性:非 WASI。

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

其中一個類,HTTPServer,是 socketserver.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)

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

class http.server.ThreadingHTTPServer(server_address, RequestHandlerClass)

此類與 HTTPServer 相同,但使用 ThreadingMixIn 使用執行緒處理請求。這對於處理網路瀏覽器預開啟套接字非常有用,否則 HTTPServer 將無限期等待。

在 3.7 版本加入。

class http.server.HTTPSServer(server_address, RequestHandlerClass, bind_and_activate=True, *, certfile, keyfile=None, password=None, alpn_protocols=None)

HTTPServer 的子類,使用 ssl 模組封裝套接字。如果 ssl 模組不可用,則例項化 HTTPSServer 物件將導致 RuntimeError 失敗。

certfile 引數是 SSL 證書鏈檔案的路徑,keyfile 是包含私鑰的檔案的路徑。

可以為受 PKCS#8 保護和封裝的檔案指定 password,但請注意,這可能會以明文形式公開硬編碼密碼。

參見

有關 certfilekeyfilepassword 接受值的更多資訊,請參閱 ssl.SSLContext.load_cert_chain()

指定時,alpn_protocols 引數必須是字串序列,指定伺服器支援的“應用層協議協商”(ALPN) 協議。ALPN 允許伺服器和客戶端在 TLS 握手期間協商應用協議。

預設情況下,它設定為 ["http/1.1"],這意味著伺服器支援 HTTP/1.1。

在 3.14 版本加入。

class http.server.ThreadingHTTPSServer(server_address, RequestHandlerClass, bind_and_activate=True, *, certfile, keyfile=None, password=None, alpn_protocols=None)

此類與 HTTPSServer 相同,但透過繼承 ThreadingMixIn 使用執行緒處理請求。這類似於 ThreadingHTTPServer,只是使用 HTTPSServer

在 3.14 版本加入。

HTTPServerThreadingHTTPServerHTTPSServerThreadingHTTPSServer 在例項化時必須給定一個 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() 返回之前應設定為 True 的布林值,指示是否可以預期另一個請求,或者是否應關閉連線。

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 屬性儲存 messageexplain 的預設值,如果未提供值,則將使用這些預設值;對於未知程式碼,兩者的預設值都是字串 ???。如果方法是 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* 給定的日期和時間(必須是 None 或以 time.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:' 標頭。

然後是一個空行,表示標頭的結束,然後輸出檔案內容。

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

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

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

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 來使用不同的索引檔名。

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

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

備註

CGIHTTPRequestHandler 類執行的 CGI 指令碼不能執行重定向 (HTTP 程式碼 302),因為在 CGI 指令碼執行之前傳送了程式碼 200 (指令碼輸出隨後)。這搶佔了狀態碼。

但是,如果它猜測是 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,“Can only POST to CGI scripts”。

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

自 3.13 版棄用,將在 3.15 版中移除: CGIHTTPRequestHandler 將在 3.15 版中移除。CGI 在十多年來一直不被認為是好的做法。這段程式碼已經有一段時間無人維護,並且實際使用量很少。保留它可能會導致進一步的安全考慮

命令列介面

http.server 也可以使用直譯器的 -m 開關直接呼叫。以下示例說明了如何提供相對於當前目錄的檔案:

python -m http.server [OPTIONS] [port]

接受以下選項

port

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

python -m http.server 9000
-b, --bind <address>

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

python -m http.server --bind 127.0.0.1

在 3.4 版本加入。

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

-d, --directory <dir>

指定伺服器應從中提供檔案的目錄。預設情況下,伺服器使用當前目錄。例如,以下命令使用特定目錄:

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

在 3.7 版本加入。

-p, --protocol <version>

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

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

在 3.11 版本中新增。

--cgi

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

python -m http.server --cgi

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

警告

CGIHTTPRequestHandler--cgi 命令列選項不適用於不受信任的客戶端,並且可能容易受到攻擊。請務必在安全環境中使用。

--tls-cert

為 HTTPS 連線指定 TLS 證書鏈。

python -m http.server --tls-cert fullchain.pem

在 3.14 版本加入。

--tls-key

為 HTTPS 連線指定私鑰檔案。

此選項需要指定 --tls-cert

在 3.14 版本加入。

--tls-password-file

為受密碼保護的私鑰指定密碼檔案。

python -m http.server \
       --tls-cert cert.pem \
       --tls-key key.pem \
       --tls-password-file password.txt

此選項需要指定 –tls-cert`

在 3.14 版本加入。

安全考慮

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

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

3.12 版中已更改: stderr 日誌中的控制字元已被清除。