http.client --- HTTP 協議客戶端?

源代碼: Lib/http/client.py


這個模塊定義了實現 HTTP 和 HTTPS 協議客戶端的類。 它通常不直接使用 --- 模塊 urllib.request 用它來處理使用 HTTP 和 HTTPS 的 URL。

參見

對于更高級別的 HTTP 客戶端接口,建議使用 Requests

注解

HTTPS 支持僅在編譯 Python 時啟用了 SSL 支持的情況下(通過 ssl 模塊)可用。

該模塊支持以下類:

class http.client.HTTPConnection(host, port=None, [timeout, ]source_address=None, blocksize=8192)?

HTTPConnection 的實例代表與 HTTP 的一個連接事務。 它的實例化應當傳入一個主機和可選的端口號。 如果沒有傳入端口號,如果主機字符串的形式為 主機:端口 則會從中提取端口,否則將使用默認的 HTTP 端口(80)。 如果給出了可選的 timeout 參數,則阻塞操作(例如連接嘗試)將在指定的秒數之后超時(如果未給出,則使用全局默認超時設置)。 可選的 source_address 參數可以為一個 (主機, 端口) 元組,用作進行 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, key_file=None, cert_file=None, [timeout, ]source_address=None, *, context=None, check_hostname=None, blocksize=8192)?

HTTPConnection 的子類,使用 SSL 與安全服務器進行通信。 默認端口為 443。 如果指定了 context,它必須為一個描述 SSL 各選項的 ssl.SSLContext 實例。

請參閱 安全考量 了解有關最佳實踐的更多信息。

在 3.2 版更改: 添加了 source_address, contextcheck_hostname

在 3.2 版更改: 這個類目前會在可能的情況下(即如果 ssl.HAS_SNI 為真值)支持 HTTPS 虛擬主機。

在 3.4 版更改: 刪除了 strict 參數,不再支持 HTTP 0.9 風格的“簡單響應”。

在 3.4.3 版更改: 目前這個類在默認情況下會執行所有必要的證書和主機檢查。 要回復到先前的非驗證行為,可以將 ssl._create_unverified_context() 傳遞給 context 參數。

在 3.7.4 版更改: 該類現在對于默認的 context 或在傳入 cert_file 并附帶自定義 context 時會啟用 TLS 1.3 ssl.SSLContext.post_handshake_auth

3.6 版后已移除: key_filecert_file 已棄用并轉而推薦 context。 請改用 ssl.SSLContext.load_cert_chain() 或讓 ssl.create_default_context() 為你選擇系統所信任的 CA 證書。

check_hostname 參數也已棄用;應當改用 contextssl.SSLContext.check_hostname 屬性。

class http.client.HTTPResponse(sock, debuglevel=0, method=None, url=None)?

在成功連接后返回類的實例,而不是由用戶直接實例化。

在 3.4 版更改: 刪除了 strict 參數,不再支持HTTP 0.9 風格的“簡單響應”。

下列異常可以適當地被引發:

exception http.client.HTTPException?

此模塊中其他異常的基類。 它是 Exception 的一個子類。

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?

ImproperConnectionState 的一個子類。

exception http.client.CannotSendHeader?

ImproperConnectionState 的一個子類。

exception http.client.ResponseNotReady?

ImproperConnectionState 的一個子類。

exception http.client.BadStatusLine?

HTTPException 的一個子類。 如果服務器反饋了一個我們不理解的 HTTP 狀態碼就會被引發。

exception http.client.LineTooLong?

HTTPException 的一個子類。 如果在 HTTP 協議中從服務器接收到過長的行就會被引發。

exception http.client.RemoteDisconnected?

ConnectionResetErrorBadStatusLine 的一個子類。 當嘗試讀取響應時的結果是未從連接讀取到數據時由 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 和選擇器 url 向服務器發送請求。

如果給定 body,那么給定的數據會在信息頭完成之后發送。它可能是一個 str 、一個 bytes-like object 、一個打開的 file object,或者 bytes 迭代器。如果 body 是字符串,它會按 HTTP 默認的 ISO-8859-1 編碼;如果是一個字節類對象,它會按原樣發送;如果是 file object ,文件的內容會被發送,這個文件對象應該支持 read() 方法。如果這個文件對象是一個 io.TextIOBase 實例, read() 方法返回的數據會按 ISO-8859-1 編碼,否則 read() 方法返回的數據會按原樣發送;如果 body 是一個迭代器,迭代器中的元素會被發送,直到迭代器耗盡。

headers 參數應是額外的隨請求發送的 HTTP 信息頭的字典。

如果 headers 既不包含 Content-Length 也沒有 Transfer-Encoding,但存在請求正文,那么這些頭字段中的一個會自動設定。如果 bodyNone,那么對于要求正文的方法 (PUTPOST,和 PATCH),Content-Length 頭會被設為 0。如果 body 是字符串或者類似字節的對象,并且也不是 文件,Content-Length 頭會設為正文的長度。任何其他類型的 body (一般是文件或迭代器)會按塊編碼,這時會自動設定 Transfer-Encoding 頭以代替 Content-Length。

headers 中指定 Transfer-Encoding 時, encode_chunked 是唯一相關的參數。如果 encode_chunkedFalse,HTTPConnection 對象會假定所有的編碼都由調用代碼處理。如果為 True,正文會按塊編碼。

注解

HTTP 協議在 1.1 版中添加了塊傳輸編碼。除非明確知道 HTTP 服務器可以處理 HTTP 1.1,調用者要么必須指定 Content-Length,要么必須傳入 str 或字節類對象,注意該對象不能是表達 body 的文件。

3.2 新版功能: body 現在可以是可迭代對象了。

在 3.6 版更改: 如果 Content-Length 和 Transfer-Encoding 都沒有在 headers 中設置,文件和可迭代的 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 連接隧道設置主機和端口。 這將允許通過代理服務器運行連接。

host 和 port 參數指明隧道連接的位置(即 CONNECT 請求所包含的地址,而 不是 代理服務器的地址)。

headers 參數應為一個隨 CONNECT 請求發送的額外 HTTP 標頭的映射。

例如,要通過一個運行于本機 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 新版功能.

HTTPConnection.connect()?

當對象被創建后連接到指定的服務器。 默認情況下,如果客戶端還未建立連接,此函數會在發送請求時自動被調用。

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_hostskip_accept_encoding 設為非 False 值。

HTTPConnection.putheader(header, argument[, ...])?

向服務器發送一個 RFC 822 格式的頭部。將向服務器發送一行由頭、冒號和空格以及第一個參數組成的數據。 如果還給出了其他參數,將在后續行中發送,每行由一個制表符和一個參數組成。

HTTPConnection.endheaders(message_body=None, *, encode_chunked=False)?

向服務器發送一個空行,表示頭部文件結束。可選的 message_body 參數可用于傳入一個與請求相關的消息體。

如果 encode_chunkedTrue,則對 message_body 的每次迭代結果將依照 RFC 7230 3.3.1 節的規范進行分塊編碼。數據如何編碼取決于 message_body 的類型。 如果 message_body 實現了 buffer 接口,編碼將生成一個數據塊。如果 message_bodycollections.abc.Iterable,則 message_body 的每次迭代都會產生一個塊。 如果 message_bodyfile object,那么每次調用 .read() 都會產生一個數據塊。在 message_body 結束后,本方法立即會自動標記塊編碼數據的結束。

注解

由于分塊編碼的規范要求,迭代器本身產生的空塊將被分塊編碼器忽略。這是為了避免目標服務器因錯誤編碼而過早終止對請求的讀取。

3.6 新版功能: 支持分塊編碼。加入了 encode_chunked 參數。

HTTPConnection.send(data)?

發送數據到服務器。本函數只應在調用 endheaders() 方法之后且調用 getresponse() 之前直接調用。

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.HTTPMessageemail.message 的子類。

HTTPResponse.version?

服務器使用的 HTTP 協議版本。10 代表 HTTP/1.0,11 代表 HTTP/1.1。

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 True:
...     chunk = r1.read(200)  # 200 bytes
...     if not chunk:
...          break
...     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="http://bugs.python.org/issue12524">http://bugs.python.org/issue12524</a>'
>>> conn.close()

在客戶端, HTTP PUT 請求與 POST 請求非常相似。區別只在于服務器端,HTTP 服務器將允許通過 PUT 請求創建資源。應該注意的是,自定義的 HTTP 方法也可以在 urllib.request.Request 中通過設置適當的方法屬性來進行處理。下面是一個會話示例,演示了如何利用 http.client 發送 PUT 請求。

>>> # This creates an HTTP message
>>> # with the content of BODY as the enclosed representation
>>> # for the resource http://localhost: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 對象?

http.client.HTTPMessage 的實例存有 HTTP 響應的頭部信息。利用 email.message.Message 類實現。