http.client
--- HTTP 協議客戶端¶
原始碼: Lib/http/client.py
此模組定義了實現 HTTP 和 HTTPS 協議客戶端的類。通常不直接使用它 —— 模組 urllib.request
使用它來處理使用 HTTP 和 HTTPS 的 URL。
參見
對於更高級別的 HTTP 客戶端介面,推薦使用 Requests 包。
備註
僅當 Python 編譯時帶有 SSL 支援(透過 ssl
模組)時,HTTPS 支援才可用。
可用性:非 WASI。
此模組在 WebAssembly 上不起作用或不可用。有關更多資訊,請參閱 WebAssembly 平臺。
此模組提供了以下類:
- class http.client.HTTPConnection(host, port=None, [timeout, ]source_address=None, blocksize=8192)¶
一個
HTTPConnection
例項表示與一個 HTTP 伺服器的一次事務。它應該透過傳遞主機和可選的埠號來例項化。如果沒有傳遞埠號,則從主機字串中提取埠(如果其形式為host:port
),否則使用預設的 HTTP 埠 (80)。如果給定了可選的 timeout 引數,阻塞操作(如連線嘗試)將在指定的秒數後超時(如果沒有給定,則使用全域性預設超時設定)。可選的 source_address 引數可以是一個 (host, port) 元組,用作發起 HTTP 連線的源地址。可選的 blocksize 引數設定了傳送類檔案訊息體的緩衝區大小(以位元組為單位)。例如,以下呼叫都會建立連線到同一主機和埠的例項:
>>> h1 = http.client.HTTPConnection('www.python.org') >>> h2 = http.client.HTTPConnection('www.python.org:80') >>> h3 = http.client.HTTPConnection('www.python.org', 80) >>> h4 = http.client.HTTPConnection('www.python.org', 80, timeout=10)
在 3.2 版本發生變更: 添加了 source_address。
在 3.4 版本發生變更: strict 引數已被移除。不再支援 HTTP 0.9 風格的“簡單響應”。
在 3.7 版本發生變更: 添加了 blocksize 引數。
- class http.client.HTTPSConnection(host, port=None, *, [timeout, ]source_address=None, context=None, blocksize=8192)¶
HTTPConnection
的一個子類,使用 SSL 與安全伺服器進行通訊。預設埠是443
。如果指定了 context,它必須是一個ssl.SSLContext
例項,用於描述各種 SSL 選項。請閱讀 安全考量 以獲取有關最佳實踐的更多資訊。
在 3.2 版本發生變更: 添加了 source_address、context 和 check_hostname。
在 3.2 版本發生變更: 此類現在在可能的情況下支援 HTTPS 虛擬主機(即,如果
ssl.HAS_SNI
為真)。在 3.4 版本發生變更: strict 引數已被移除。不再支援 HTTP 0.9 風格的“簡單響應”。
在 3.4.3 版本發生變更: 此類現在預設執行所有必要的證書和主機名檢查。要恢復到以前未驗證的行為,可以將
ssl._create_unverified_context()
傳遞給 context 引數。在 3.8 版本發生變更: 對於預設的 context,或者當使用自定義 context 傳遞 cert_file 時,此類現在會為
ssl.SSLContext.post_handshake_auth
啟用 TLS 1.3。在 3.10 版本發生變更: 當沒有提供 context 時,此類現在會發送一個帶有協議指示符
http/1.1
的 ALPN 擴充套件。自定義的 context 應使用set_alpn_protocols()
來設定 ALPN 協議。在 3.12 版本發生變更: 已移除已棄用的 key_file、cert_file 和 check_hostname 引數。
- class http.client.HTTPResponse(sock, debuglevel=0, method=None, url=None)¶
連線成功後返回其例項的類。不由使用者直接例項化。
在 3.4 版本發生變更: strict 引數已被移除。不再支援 HTTP 0.9 風格的“簡單響應”。
此模組提供了以下函式:
- http.client.parse_headers(fp)¶
從一個代表 HTTP 請求/響應的檔案指標 fp 中解析標頭。該檔案必須是一個
BufferedIOBase
讀取器(即非文字),並且必須提供一個有效的 RFC 2822 風格的標頭。此函式返回一個
http.client.HTTPMessage
的例項,該例項包含標頭欄位,但沒有有效負載(與HTTPResponse.msg
和http.server.BaseHTTPRequestHandler.headers
相同)。返回後,檔案指標 fp 已準備好讀取 HTTP 主體。備註
parse_headers()
不解析 HTTP 訊息的起始行;它只解析Name: value
格式的行。檔案必須已準備好讀取這些欄位行,因此在呼叫該函式之前,第一行應已被消費。
以下異常會在適當的時候被引發:
- exception http.client.NotConnected¶
HTTPException
的子類。
- exception http.client.InvalidURL¶
HTTPException
的子類,在給定的埠非數字或為空時引發。
- exception http.client.UnknownProtocol¶
HTTPException
的子類。
- exception http.client.UnknownTransferEncoding¶
HTTPException
的子類。
- exception http.client.UnimplementedFileMode¶
HTTPException
的子類。
- exception http.client.IncompleteRead¶
HTTPException
的子類。
- exception http.client.ImproperConnectionState¶
HTTPException
的子類。
- exception http.client.CannotSendRequest¶
- exception http.client.CannotSendHeader¶
- exception http.client.ResponseNotReady¶
- exception http.client.BadStatusLine¶
HTTPException
的子類。如果伺服器響應了我們不理解的 HTTP 狀態碼,則會引發此異常。
- exception http.client.LineTooLong¶
HTTPException
的子類。在從伺服器接收到的 HTTP 協議中出現過長的行時引發。
- exception http.client.RemoteDisconnected¶
ConnectionResetError
和BadStatusLine
的子類。由HTTPConnection.getresponse()
在嘗試讀取響應時沒有從連線中讀取到任何資料時引發,這表明遠端端已關閉連線。在 3.5 版本加入: 以前,會引發
BadStatusLine
('')
。
此模組中定義的常量是:
- http.client.HTTP_PORT¶
HTTP 協議的預設埠(總是
80
)。
- http.client.HTTPS_PORT¶
HTTPS 協議的預設埠(總是
443
)。
- http.client.responses¶
此字典將 HTTP 1.1 狀態碼對映到 W3C 名稱。
示例:
http.client.responses[http.client.NOT_FOUND]
是'Not Found'
。
請參閱 HTTP 狀態碼 獲取此模組中可作為常量的 HTTP 狀態碼列表。
HTTPConnection 物件¶
HTTPConnection
例項有以下方法:
- HTTPConnection.request(method, url, body=None, headers={}, *, encode_chunked=False)¶
這將使用 HTTP 請求方法 method 和請求 URI url 向伺服器傳送請求。提供的 url 必須是絕對路徑,以符合 RFC 2616 §5.1.2(除非連線到 HTTP 代理伺服器或使用
OPTIONS
或CONNECT
方法)。如果指定了 body,則在標頭完成後傳送指定的資料。它可以是一個
str
、一個類位元組物件、一個開啟的檔案物件,或者一個bytes
的可迭代物件。如果 body 是一個字串,它會以 ISO-8859-1 編碼,這是 HTTP 的預設編碼。如果它是一個類位元組物件,則按原樣傳送位元組。如果它是一個檔案物件,則傳送檔案的內容;此檔案物件應至少支援read()
方法。如果檔案物件是io.TextIOBase
的例項,read()
方法返回的資料將以 ISO-8859-1 編碼,否則read()
返回的資料將按原樣傳送。如果 body 是一個可迭代物件,則可迭代物件的元素將按原樣傳送,直到可迭代物件耗盡。headers 引數應該是一個與請求一起傳送的額外 HTTP 標頭的對映。必須提供一個 Host 標頭,以符合 RFC 2616 §5.1.2(除非連線到 HTTP 代理伺服器或使用
OPTIONS
或CONNECT
方法)。如果 headers 中既不包含 Content-Length 也不包含 Transfer-Encoding,但存在請求體,則會自動新增其中一個標頭欄位。如果 body 為
None
,對於需要主體的請求方法(PUT
、POST
和PATCH
),Content-Length 標頭將被設定為0
。如果 body 是一個字串或一個非檔案的類位元組物件,Content-Length 標頭將被設定為其長度。任何其他型別的 body(通常是檔案和可迭代物件)將被分塊編碼,並且會自動設定 Transfer-Encoding 標頭而不是 Content-Length。encode_chunked 引數僅在 headers 中指定了 Transfer-Encoding 時才相關。如果 encode_chunked 為
False
,HTTPConnection 物件假定所有編碼都由呼叫程式碼處理。如果為True
,主體將被分塊編碼。例如,要向
https://docs.python.club.tw/3/
傳送一個GET
請求:>>> import http.client >>> host = "docs.python.org" >>> conn = http.client.HTTPSConnection(host) >>> conn.request("GET", "/3/", headers={"Host": host}) >>> response = conn.getresponse() >>> print(response.status, response.reason) 200 OK
備註
分塊傳輸編碼已新增到 HTTP 協議 1.1 版本中。除非已知 HTTP 伺服器能處理 HTTP 1.1,否則呼叫者必須指定 Content-Length,或者必須傳遞一個
str
或一個非檔案的類位元組物件作為主體表示。在 3.2 版本發生變更: body 現在可以是一個可迭代物件。
在 3.6 版本發生變更: 如果 headers 中既未設定 Content-Length 也未設定 Transfer-Encoding,檔案和可迭代的 body 物件現在會被分塊編碼。添加了 encode_chunked 引數。不會嘗試為檔案物件確定 Content-Length。
- HTTPConnection.getresponse()¶
應在傳送請求後呼叫,以獲取伺服器的響應。返回一個
HTTPResponse
例項。備註
請注意,您必須在向伺服器傳送新請求之前讀取完整的響應。
在 3.5 版本發生變更: 如果引發了
ConnectionError
或其子類,HTTPConnection
物件將在傳送新請求時準備好重新連線。
- HTTPConnection.set_debuglevel(level)¶
設定除錯級別。預設除錯級別為
0
,表示不列印除錯輸出。任何大於0
的值都會導致所有當前定義的除錯輸出列印到 stdout。debuglevel
會傳遞給任何新建立的HTTPResponse
物件。在 3.1 版本加入。
- HTTPConnection.set_tunnel(host, port=None, headers=None)¶
設定用於 HTTP CONNECT 隧道的主機和埠。這允許透過代理伺服器執行連線。
host 和 port 引數指定隧道連線的端點(即包含在 CONNECT 請求中的地址,而不是代理伺服器的地址)。
headers 引數應該是一個與 CONNECT 請求一起傳送的額外 HTTP 標頭的對映。
根據 RFC 的規定,HTTP CONNECT 隧道請求使用 HTTP/1.1,因此必須提供一個 HTTP
Host:
標頭,該標頭必須與作為 CONNECT 請求目標的 authority-form 形式的請求目標相匹配。如果未透過 headers 引數提供 HTTPHost:
標頭,則會自動生成並傳輸一個。例如,要透過在本地埠 8080 上執行的 HTTPS 代理伺服器進行隧道,我們會將代理的地址傳遞給
HTTPSConnection
建構函式,並將我們最終想要訪問的主機地址傳遞給set_tunnel()
方法:>>> import http.client >>> conn = http.client.HTTPSConnection("localhost", 8080) >>> conn.set_tunnel("www.python.org") >>> conn.request("HEAD","/index.html")
在 3.2 版本加入。
在 3.12 版本發生變更: HTTP CONNECT 隧道請求使用 HTTP/1.1 協議,從 HTTP/1.0 協議升級而來。
Host:
HTTP 標頭對於 HTTP/1.1 是強制性的,因此如果 headers 引數中未提供,將自動生成並傳輸一個。
- HTTPConnection.get_proxy_response_headers()¶
返回一個字典,其中包含從代理伺服器收到的對 CONNECT 請求的響應標頭。
如果未傳送 CONNECT 請求,則此方法返回
None
。3.12 新版功能.
- HTTPConnection.connect()¶
連線到建立物件時指定的伺服器。預設情況下,如果客戶端尚未建立連線,則在發出請求時會自動呼叫此方法。
引發一個 審計事件
http.client.connect
,附帶引數self
,host
,port
。
- HTTPConnection.close()¶
關閉與伺服器的連線。
- HTTPConnection.blocksize¶
用於傳送類檔案訊息體的緩衝區大小(以位元組為單位)。
在 3.7 版本加入。
作為使用上述 request()
方法的替代方案,您還可以透過使用下面的四個函式來逐步傳送請求。
- HTTPConnection.putrequest(method, url, skip_host=False, skip_accept_encoding=False)¶
這應該是與伺服器建立連線後的第一個呼叫。它向伺服器傳送一行,包括 method 字串、url 字串和 HTTP 版本(
HTTP/1.1
)。要停用自動傳送Host:
或Accept-Encoding:
標頭(例如,為了接受額外的內容編碼),請為 skip_host 或 skip_accept_encoding 指定非 False 值。
- HTTPConnection.putheader(header, argument[, ...])¶
向伺服器傳送一個 RFC 822 風格的標頭。它向伺服器傳送一行,包括標頭、一個冒號和一個空格,以及第一個引數。如果給出更多引數,則會發送續行,每行由一個製表符和一個引數組成。
- HTTPConnection.endheaders(message_body=None, *, encode_chunked=False)¶
向伺服器傳送一個空行,表示標頭結束。可選的 message_body 引數可用於傳遞與請求相關的訊息體。
如果 encode_chunked 為
True
,message_body 的每次迭代結果將按照 RFC 7230 第 3.3.1 節的規定進行分塊編碼。資料的編碼方式取決於 message_body 的型別。如果 message_body 實現了 緩衝區介面,編碼將產生一個單獨的資料塊。如果 message_body 是一個collections.abc.Iterable
,message_body 的每次迭代將產生一個數據塊。如果 message_body 是一個檔案物件,每次呼叫.read()
將產生一個數據塊。此方法在 message_body 結束後立即自動發出分塊編碼資料結束的訊號。備註
由於分塊編碼規範,迭代器主體產生的空塊將被分塊編碼器忽略。這是為了避免由於格式錯誤的編碼而導致目標伺服器提前終止對請求的讀取。
在 3.6 版本發生變更: 添加了分塊編碼支援和 encode_chunked 引數。
- HTTPConnection.send(data)¶
向伺服器傳送資料。這應該僅在呼叫了
endheaders()
方法之後且在呼叫getresponse()
之前直接使用。引發一個 審計事件
http.client.send
,附帶引數self
,data
。
HTTPResponse 物件¶
一個 HTTPResponse
例項包裝了來自伺服器的 HTTP 響應。它提供了對請求標頭和實體主體的訪問。響應是一個可迭代物件,可以在 with 語句中使用。
在 3.5 版本發生變更: 現在實現了 io.BufferedIOBase
介面,並支援其所有的讀取器操作。
- HTTPResponse.read([amt])¶
讀取並返回響應體,或者最多讀取接下來的 amt 個位元組。
- HTTPResponse.readinto(b)¶
將響應體中最多接下來的 len(b) 個位元組讀入緩衝區 b。返回讀取的位元組數。
在 3.3 版本加入。
- HTTPResponse.getheader(name, default=None)¶
返回標頭 name 的值,如果沒有匹配 name 的標頭,則返回 default。如果存在多個同名 name 的標頭,則返回所有值並用 ‘, ’ 連線。如果 default 是除單個字串外的任何可迭代物件,其元素同樣會用逗號連線後返回。
- HTTPResponse.getheaders()¶
返回一個 (header, value) 元組列表。
- HTTPResponse.fileno()¶
返回底層套接字的
fileno
。
- HTTPResponse.msg¶
一個包含響應標頭的
http.client.HTTPMessage
例項。http.client.HTTPMessage
是email.message.Message
的子類。
- HTTPResponse.version¶
伺服器使用的 HTTP 協議版本。HTTP/1.0 為 10,HTTP/1.1 為 11。
- HTTPResponse.url¶
所檢索資源的 URL,通常用於確定是否發生了重定向。
- HTTPResponse.headers¶
響應的標頭,形式為
email.message.EmailMessage
例項。
- HTTPResponse.status¶
伺服器返回的狀態碼。
- HTTPResponse.reason¶
伺服器返回的原因短語。
- HTTPResponse.debuglevel¶
一個除錯鉤子。如果
debuglevel
大於零,在讀取和解析響應時,訊息將被列印到 stdout。
- HTTPResponse.closed¶
如果流已關閉,則為
True
。
示例¶
以下是使用 GET
方法的示例會話:
>>> import http.client
>>> conn = http.client.HTTPSConnection("www.python.org")
>>> conn.request("GET", "/")
>>> r1 = conn.getresponse()
>>> print(r1.status, r1.reason)
200 OK
>>> data1 = r1.read() # This will return entire content.
>>> # The following example demonstrates reading data in chunks.
>>> conn.request("GET", "/")
>>> r1 = conn.getresponse()
>>> while chunk := r1.read(200):
... print(repr(chunk))
b'<!doctype html>\n<!--[if"...
...
>>> # Example of an invalid request
>>> conn = http.client.HTTPSConnection("docs.python.org")
>>> conn.request("GET", "/parrot.spam")
>>> r2 = conn.getresponse()
>>> print(r2.status, r2.reason)
404 Not Found
>>> data2 = r2.read()
>>> conn.close()
以下是使用 HEAD
方法的示例會話。請注意,HEAD
方法從不返回任何資料。
>>> import http.client
>>> conn = http.client.HTTPSConnection("www.python.org")
>>> conn.request("HEAD", "/")
>>> res = conn.getresponse()
>>> print(res.status, res.reason)
200 OK
>>> data = res.read()
>>> print(len(data))
0
>>> data == b''
True
以下是使用 POST
方法的示例會話:
>>> import http.client, urllib.parse
>>> params = urllib.parse.urlencode({'@number': 12524, '@type': 'issue', '@action': 'show'})
>>> headers = {"Content-type": "application/x-www-form-urlencoded",
... "Accept": "text/plain"}
>>> conn = http.client.HTTPConnection("bugs.python.org")
>>> conn.request("POST", "", params, headers)
>>> response = conn.getresponse()
>>> print(response.status, response.reason)
302 Found
>>> data = response.read()
>>> data
b'Redirecting to <a href="https://bugs.python.org/issue12524">https://bugs.python.org/issue12524</a>'
>>> conn.close()
客戶端的 HTTP PUT
請求與 POST
請求非常相似。區別僅在於伺服器端,HTTP 伺服器會允許透過 PUT
請求建立資源。需要注意的是,自定義 HTTP 方法也在 urllib.request.Request
中透過設定相應的方法屬性來處理。以下是使用 PUT
方法的示例會話:
>>> # This creates an HTTP request
>>> # with the content of BODY as the enclosed representation
>>> # for the resource https://:8080/file
...
>>> import http.client
>>> BODY = "***filecontents***"
>>> conn = http.client.HTTPConnection("localhost", 8080)
>>> conn.request("PUT", "/file", BODY)
>>> response = conn.getresponse()
>>> print(response.status, response.reason)
200, OK
HTTPMessage 物件¶
- class http.client.HTTPMessage(email.message.Message)¶
一個 http.client.HTTPMessage
例項持有來自 HTTP 響應的標頭。它是使用 email.message.Message
類實現的。