http.client
--- HTTP 協(xié)議客戶(hù)端?
源代碼: Lib/http/client.py
這個(gè)模塊定義了實(shí)現 HTTP 和 HTTPS 協(xié)議客戶(hù)端的類(lèi)。 它通常不直接使用 --- 模塊 urllib.request
用它來(lái)處理使用 HTTP 和 HTTPS 的 URL。
參見(jiàn)
對于更高級別的 HTTP 客戶(hù)端接口,建議使用 Requests 。
備注
HTTPS 支持僅在編譯 Python 時(shí)啟用了 SSL 支持的情況下(通過(guò) ssl
模塊)可用。
該模塊支持以下類(lèi):
- class http.client.HTTPConnection(host, port=None, [timeout, ]source_address=None, blocksize=8192)?
HTTPConnection
的實(shí)例代表與 HTTP 的一個(gè)連接事務(wù)。 它的實(shí)例化應當傳入一個(gè)主機和可選的端口號。 如果沒(méi)有傳入端口號,如果主機字符串的形式為主機:端口
則會(huì )從中提取端口,否則將使用默認的 HTTP 端口(80)。 如果給出了可選的 timeout 參數,則阻塞操作(例如連接嘗試)將在指定的秒數之后超時(shí)(如果未給出,則使用全局默認超時(shí)設置)。 可選的 source_address 參數可以為一個(gè) (主機, 端口) 元組,用作進(jìn)行 HTTP 連接的源地址。 可選的 blocksize 參數可以字節為單位設置緩沖區的大小,用來(lái)發(fā)送文件類(lèi)消息體。舉個(gè)例子,以下調用都是創(chuàng )建連接到同一主機和端口的服務(wù)器的實(shí)例:
>>> 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 風(fēng)格的“簡(jiǎn)單響應”。
在 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
的子類(lèi),使用 SSL 與安全服務(wù)器進(jìn)行通信。 默認端口為443
。 如果指定了 context,它必須為一個(gè)描述 SSL 各選項的ssl.SSLContext
實(shí)例。請參閱 安全考量 了解有關(guān)最佳實(shí)踐的更多信息。
在 3.2 版更改: 添加了 source_address, context 和 check_hostname。
在 3.2 版更改: 這個(gè)類(lèi)目前會(huì )在可能的情況下(即如果
ssl.HAS_SNI
為真值)支持 HTTPS 虛擬主機。在 3.4 版更改: 刪除了 strict 參數,不再支持 HTTP 0.9 風(fēng)格的“簡(jiǎn)單響應”。
在 3.4.3 版更改: 目前這個(gè)類(lèi)在默認情況下會(huì )執行所有必要的證書(shū)和主機檢查。 要回復到先前的非驗證行為,可以將
ssl._create_unverified_context()
傳遞給 context 參數。在 3.8 版更改: 該類(lèi)現在對于默認的 context 或在傳入 cert_file 并附帶自定義 context 時(shí)會(huì )啟用 TLS 1.3
ssl.SSLContext.post_handshake_auth
。在 3.10 版更改: 現在,若未給出 context,則會(huì )發(fā)送一個(gè)帶有協(xié)議指示器
http/1.1
的ALPN 擴展。自定義 context 應用set_alpn_protocol()
設置 ALPN 協(xié)議。3.6 版后已移除: key_file 和 cert_file 已棄用并轉而推薦 context。 請改用
ssl.SSLContext.load_cert_chain()
或讓ssl.create_default_context()
為你選擇系統所信任的 CA 證書(shū)。check_hostname 參數也已棄用;應當改用 context 的
ssl.SSLContext.check_hostname
屬性。
- class http.client.HTTPResponse(sock, debuglevel=0, method=None, url=None)?
在成功連接后返回類(lèi)的實(shí)例,而不是由用戶(hù)直接實(shí)例化。
在 3.4 版更改: 刪除了 strict 參數,不再支持HTTP 0.9 風(fēng)格的“簡(jiǎn)單響應”。
這個(gè)模塊定義了以下函數:
- http.client.parse_headers(fp)?
從文件指針 fp 中解析頭部信息,該文件代表 HTTP 請求/響應。該文件必須是
BufferedIOBase
reader 對象(即不是文本),并且必須提供符合 RFC 2822 格式的頭部。該函數返回
http.client.HTTPMessage
的實(shí)例,帶有頭部各個(gè)字段,但不帶正文數據(與HTTPResponse.msg
和http.server.BaseHTTPRequestHandler.headers
一樣)。返回之后,文件指針 fp 已為讀取 HTTP 正文做好準備了。備注
parse_headers()
不會(huì )解析 HTTP 消息的開(kāi)始行;只會(huì )解析各Name: value
行。文件必須為讀取這些字段做好準備,所以在調用該函數之前,第一行應該已經(jīng)被讀取過(guò)了。
下列異??梢赃m當地被引發(fā):
- exception http.client.NotConnected?
HTTPException
的一個(gè)子類(lèi)。
- exception http.client.InvalidURL?
HTTPException
的一個(gè)子類(lèi),如果給出了一個(gè)非數字或為空值的端口就會(huì )被引發(fā)。
- exception http.client.UnknownProtocol?
HTTPException
的一個(gè)子類(lèi)。
- exception http.client.UnknownTransferEncoding?
HTTPException
的一個(gè)子類(lèi)。
- exception http.client.UnimplementedFileMode?
HTTPException
的一個(gè)子類(lèi)。
- exception http.client.IncompleteRead?
HTTPException
的一個(gè)子類(lèi)。
- exception http.client.ImproperConnectionState?
HTTPException
的一個(gè)子類(lèi)。
- exception http.client.CannotSendRequest?
ImproperConnectionState
的一個(gè)子類(lèi)。
- exception http.client.CannotSendHeader?
ImproperConnectionState
的一個(gè)子類(lèi)。
- exception http.client.ResponseNotReady?
ImproperConnectionState
的一個(gè)子類(lèi)。
- exception http.client.BadStatusLine?
HTTPException
的一個(gè)子類(lèi)。 如果服務(wù)器反饋了一個(gè)我們不理解的 HTTP 狀態(tài)碼就會(huì )被引發(fā)。
- exception http.client.LineTooLong?
HTTPException
的一個(gè)子類(lèi)。 如果在 HTTP 協(xié)議中從服務(wù)器接收到過(guò)長(cháng)的行就會(huì )被引發(fā)。
- exception http.client.RemoteDisconnected?
ConnectionResetError
和BadStatusLine
的一個(gè)子類(lèi)。 當嘗試讀取響應時(shí)的結果是未從連接讀取到數據時(shí)由HTTPConnection.getresponse()
引發(fā),表明遠端已關(guān)閉連接。3.5 新版功能: 在此之前引發(fā)的異常為
BadStatusLine
('')
。
此模塊中定義的常量為:
- http.client.HTTP_PORT?
HTTP 協(xié)議默認的端口號 (總是
80
)。
- http.client.HTTPS_PORT?
HTTPS 協(xié)議默認的端口號 (總是
443
)。
- http.client.responses?
這個(gè)字典把 HTTP 1.1 狀態(tài)碼映射到 W3C 名稱(chēng)。
例如:
http.client.responses[http.client.NOT_FOUND]
是'NOT FOUND
(未發(fā)現)。
本模塊中可用的 HTTP 狀態(tài)碼常量可以參見(jiàn) HTTP 狀態(tài)碼 。
HTTPConnection 對象?
HTTPConnection
實(shí)例擁有以下方法:
- HTTPConnection.request(method, url, body=None, headers={}, *, encode_chunked=False)?
這會(huì )使用 HTTP 請求方法 method 和選擇器 url 向服務(wù)器發(fā)送請求。
如果給定 body,那么給定的數據會(huì )在信息頭完成之后發(fā)送。它可能是一個(gè)
字符串
,一個(gè) bytes-like object,一個(gè)打開(kāi)的 file object,或者bytes
迭代器。如果 body 是字符串,它會(huì )按 HTTP 默認的 ISO-8859-1 編碼。如果是一個(gè)字節類(lèi)對象,它會(huì )按原樣發(fā)送。如果是 file object,文件的內容會(huì )被發(fā)送,這個(gè)文件對象應該至少支持``read()`` 方法。如果這個(gè)文件對象是一個(gè)io.TextIOBase
實(shí)例,由read()
方法返回的數據會(huì )按 ISO-8859-1 編碼,否則由read()
方法返回的數據會(huì )按原樣發(fā)送。如果 body 是一個(gè)迭代器,迭代器中的元素會(huì )被發(fā)送,直到迭代器耗盡。headers 參數應是額外的隨請求發(fā)送的 HTTP 信息頭的字典。
如果 headers 既不包含 Content-Length 也沒(méi)有 Transfer-Encoding,但存在請求正文,那么這些頭字段中的一個(gè)會(huì )自動(dòng)設定。如果 body 是
None
,那么對于要求正文的方法 (PUT
,POST
,和PATCH
),Content-Length 頭會(huì )被設為0
。如果 body 是字符串或者類(lèi)似字節的對象,并且也不是 文件,Content-Length 頭會(huì )設為正文的長(cháng)度。任何其他類(lèi)型的 body (一般是文件或迭代器)會(huì )按塊編碼,這時(shí)會(huì )自動(dòng)設定 Transfer-Encoding 頭以代替 Content-Length。在 headers 中指定 Transfer-Encoding 時(shí), encode_chunked 是唯一相關(guān)的參數。如果 encode_chunked 為
False
,HTTPConnection 對象會(huì )假定所有的編碼都由調用代碼處理。如果為True
,正文會(huì )按塊編碼。備注
HTTP 協(xié)議在 1.1 版中添加了塊傳輸編碼。除非明確知道 HTTP 服務(wù)器可以處理 HTTP 1.1,調用者要么必須指定 Content-Length,要么必須傳入
str
或字節類(lèi)對象,注意該對象不能是表達 body 的文件。3.2 新版功能: body 現在可以是可迭代對象了。
在 3.6 版更改: 如果 Content-Length 和 Transfer-Encoding 都沒(méi)有在 headers 中設置,文件和可迭代的 body 對象現在會(huì )按塊編碼。添加了 encode_chunked 參數。不會(huì )嘗試去確定文件對象的 Content-Length。
- HTTPConnection.getresponse()?
應當在發(fā)送一個(gè)請求從服務(wù)器獲取響應時(shí)被調用。 返回一個(gè)
HTTPResponse
的實(shí)例。備注
請注意你必須在讀取了整個(gè)響應之后才能向服務(wù)器發(fā)送新的請求。
在 3.5 版更改: 如果引發(fā)了
ConnectionError
或其子類(lèi),HTTPConnection
對象將在發(fā)送新的請求時(shí)準備好重新連接。
- HTTPConnection.set_debuglevel(level)?
設置調試等級。 默認的調試等級為
0
,意味著(zhù)不會(huì )打印調試輸出。 任何大于0
的值將使得所有當前定義的調試輸出被打印到 stdout。debuglevel
會(huì )被傳給任何新創(chuàng )建的HTTPResponse
對象。3.1 新版功能.
- HTTPConnection.set_tunnel(host, port=None, headers=None)?
為 HTTP 連接隧道設置主機和端口。 這將允許通過(guò)代理服務(wù)器運行連接。
host 和 port 參數指明隧道連接的位置(即 CONNECT 請求所包含的地址,而 不是 代理服務(wù)器的地址)。
headers 參數應為一個(gè)隨 CONNECT 請求發(fā)送的額外 HTTP 標頭的映射。
例如,要通過(guò)一個(gè)運行于本機 8080 端口的 HTTPS 代理服務(wù)器隧道,我們應當向
HTTPSConnection
構造器傳入代理的地址,并將我們最終想要訪(fǎng)問(wèn)的主機地址傳給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()?
當對象被創(chuàng )建后連接到指定的服務(wù)器。 默認情況下,如果客戶(hù)端還未建立連接,此函數會(huì )在發(fā)送請求時(shí)自動(dòng)被調用。
觸發(fā) 音頻事件
http.client.connect
,帶有self
、host
、port
參數。
- HTTPConnection.close()?
關(guān)閉到服務(wù)器的連接。
- HTTPConnection.blocksize?
用于發(fā)送文件類(lèi)消息體的緩沖區大小。
3.7 新版功能.
作為對使用上述 request()
方法的替代同,你也可以通過(guò)使用下面的四個(gè)函數,分步驟發(fā)送請的請求。
- HTTPConnection.putrequest(method, url, skip_host=False, skip_accept_encoding=False)?
應為連接服務(wù)器之后首先調用的函數。將向服務(wù)器發(fā)送一行數據,包含 method 字符串、url 字符串和 HTTP 版本(
HTTP/1.1
)。若要禁止自動(dòng)發(fā)送Host:
或Accept-Encoding:
頭部信息(比如需要接受其他編碼格式的內容),請將 skip_host 或 skip_accept_encoding 設為非 False 值。
- HTTPConnection.putheader(header, argument[, ...])?
向服務(wù)器發(fā)送一個(gè) RFC 822 格式的頭部。將向服務(wù)器發(fā)送一行由頭、冒號和空格以及第一個(gè)參數組成的數據。 如果還給出了其他參數,將在后續行中發(fā)送,每行由一個(gè)制表符和一個(gè)參數組成。
- HTTPConnection.endheaders(message_body=None, *, encode_chunked=False)?
向服務(wù)器發(fā)送一個(gè)空行,表示頭部文件結束??蛇x的 message_body 參數可用于傳入一個(gè)與請求相關(guān)的消息體。
如果 encode_chunked 為
True
,則對 message_body 的每次迭代結果將依照 RFC 7230 3.3.1 節的規范進(jìn)行分塊編碼。數據如何編碼取決于 message_body 的類(lèi)型。 如果 message_body 實(shí)現了 buffer 接口,編碼將生成一個(gè)數據塊。如果 message_body 是collections.abc.Iterable
,則 message_body 的每次迭代都會(huì )產(chǎn)生一個(gè)塊。 如果 message_body 為 file object,那么每次調用.read()
都會(huì )產(chǎn)生一個(gè)數據塊。在 message_body 結束后,本方法立即會(huì )自動(dòng)標記分塊編碼數據的結束。備注
由于分塊編碼的規范要求,迭代器本身產(chǎn)生的空塊將被分塊編碼器忽略。這是為了避免目標服務(wù)器因錯誤編碼而過(guò)早終止對請求的讀取。
3.6 新版功能: 支持分塊編碼。加入了 encode_chunked 參數。
- HTTPConnection.send(data)?
發(fā)送數據到服務(wù)器。本函數只應在調用
endheaders()
方法之后且調用getresponse()
之前直接調用。觸發(fā) 音頻事件
http.client.send
,參數為self
、data
。
HTTPResponse 對象?
HTTPResponse
實(shí)例封裝了來(lái)自服務(wù)器的 HTTP 響應。通過(guò)它可以訪(fǎng)問(wèn)請求頭和響應體。響應是可迭代對象,可在 with 語(yǔ)句中使用。
在 3.5 版更改: 現在已實(shí)現了 io.BufferedIOBase
接口,并且支持所有的讀取操作。
- HTTPResponse.read([amt])?
讀取并返回響應體,或后續 amt 個(gè)字節。
- HTTPResponse.readinto(b)?
讀取響應體的后續 len(b) 個(gè)字節到緩沖區 b。返回讀取的字節數。
3.3 新版功能.
- HTTPResponse.getheader(name, default=None)?
返回頭部信息中的 name 值,如果沒(méi)有與 name 匹配的字段,則返回*default*。如果名為 name 的字段不止一個(gè),則返回所有字段,中間用 ', ' 連接。 如果 'default' 不是單個(gè)字符串,而是其他可迭代對象,則其元素同樣以逗號連接并返回。
- HTTPResponse.getheaders()?
返回 (header, value) 元組構成的列表。
- HTTPResponse.fileno()?
返回底層套接字的
fileno
。
- HTTPResponse.msg?
包含響應頭的
http.client.HTTPMessage
實(shí)例。http.client.HTTPMessage
是email.message
的子類(lèi)。
- HTTPResponse.version?
服務(wù)器采用的 HTTP 協(xié)議版本。10 代表 HTTP/1.0,11 代表 HTTP/1.1。
- HTTPResponse.url?
已讀取資源的 URL,通常用于確定是否進(jìn)行了重定向。
- HTTPResponse.headers?
響應的頭部信息,形式為
email.message.EmailMessage
的實(shí)例。
- HTTPResponse.status?
由服務(wù)器返回的狀態(tài)碼。
- HTTPResponse.reason?
服務(wù)器返回的原因短語(yǔ)。
- HTTPResponse.debuglevel?
一個(gè)調試鉤子。如果
debuglevel
大于零,狀態(tài)信息將在讀取和解析響應數據時(shí)打印輸出到 stdout。
- HTTPResponse.closed?
如果流被關(guān)閉,則為``True``。
例子?
下面是使用 GET
方法的會(huì )話(huà)示例:
>>> 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
方法的會(huì )話(huà)示例。 請注意,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
發(fā)送請求的會(huì )話(huà)示例:
>>> 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
>>> conn.close()
在客戶(hù)端, HTTP PUT
請求與 POST
請求非常相似。區別只在于服務(wù)器端,HTTP 服務(wù)器將允許通過(guò) PUT
請求創(chuàng )建資源。應該注意的是,自定義的 HTTP 方法也可以在 urllib.request.Request
中通過(guò)設置適當的方法屬性來(lái)進(jìn)行處理。下面是一個(gè)會(huì )話(huà)示例,演示了如何利用 http.client 發(fā)送 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
的實(shí)例存有 HTTP 響應的頭部信息。利用 email.message.Message
類(lèi)實(shí)現。