http.client --- HTTP 協(xié)議客戶端?

源代碼: Lib/http/client.py


這個(gè)模塊定義了實(shí)現(xiàn) HTTP 和 HTTPS 協(xié)議客戶端的類。 它通常不直接使用 --- 模塊 urllib.request 用它來(lái)處理使用 HTTP 和 HTTPS 的 URL。

參見

對(duì)于更高級(jí)別的 HTTP 客戶端接口,建議使用 Requests 。

備注

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

該模塊支持以下類:

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

HTTPConnection 的實(shí)例代表與 HTTP 的一個(gè)連接事務(wù)。 它的實(shí)例化應(yīng)當(dāng)傳入一個(gè)主機(jī)和可選的端口號(hào)。 如果沒有傳入端口號(hào),如果主機(jī)字符串的形式為 主機(jī):端口 則會(huì)從中提取端口,否則將使用默認(rèn)的 HTTP 端口(80)。 如果給出了可選的 timeout 參數(shù),則阻塞操作(例如連接嘗試)將在指定的秒數(shù)之后超時(shí)(如果未給出,則使用全局默認(rèn)超時(shí)設(shè)置)。 可選的 source_address 參數(shù)可以為一個(gè) (主機(jī), 端口) 元組,用作進(jìn)行 HTTP 連接的源地址。 可選的 blocksize 參數(shù)可以字節(jié)為單位設(shè)置緩沖區(qū)的大小,用來(lái)發(fā)送文件類消息體。

舉個(gè)例子,以下調(diào)用都是創(chuàng)建連接到同一主機(jī)和端口的服務(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* 參數(shù)

在 3.4 版更改: 刪除了 strict 參數(shù),不再支持 HTTP 0.9 風(fēng)格的“簡(jiǎn)單響應(yīng)”。

在 3.7 版更改: 添加了 blocksize 參數(shù)。

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 與安全服務(wù)器進(jìn)行通信。 默認(rèn)端口為 443。 如果指定了 context,它必須為一個(gè)描述 SSL 各選項(xiàng)的 ssl.SSLContext 實(shí)例。

請(qǐng)參閱 安全考量 了解有關(guān)最佳實(shí)踐的更多信息。

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

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

在 3.4 版更改: 刪除了 strict 參數(shù),不再支持 HTTP 0.9 風(fēng)格的“簡(jiǎn)單響應(yīng)”。

在 3.4.3 版更改: 目前這個(gè)類在默認(rèn)情況下會(huì)執(zhí)行所有必要的證書和主機(jī)檢查。 要回復(fù)到先前的非驗(yàn)證行為,可以將 ssl._create_unverified_context() 傳遞給 context 參數(shù)。

在 3.8 版更改: 該類現(xiàn)在對(duì)于默認(rèn)的 context 或在傳入 cert_file 并附帶自定義 context 時(shí)會(huì)啟用 TLS 1.3 ssl.SSLContext.post_handshake_auth

在 3.10 版更改: 現(xiàn)在,若未給出 context,則會(huì)發(fā)送一個(gè)帶有協(xié)議指示器 http/1.1 的ALPN 擴(kuò)展。自定義 context 應(yīng)用 set_alpn_protocol() 設(shè)置 ALPN 協(xié)議。

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

check_hostname 參數(shù)也已棄用;應(yīng)當(dāng)改用 contextssl.SSLContext.check_hostname 屬性。

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

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

在 3.4 版更改: 刪除了 strict 參數(shù),不再支持HTTP 0.9 風(fēng)格的“簡(jiǎn)單響應(yīng)”。

這個(gè)模塊定義了以下函數(shù):

http.client.parse_headers(fp)?

從文件指針 fp 中解析頭部信息,該文件代表 HTTP 請(qǐng)求/響應(yīng)。該文件必須是 BufferedIOBase reader 對(duì)象(即不是文本),并且必須提供符合 RFC 2822 格式的頭部。

該函數(shù)返回 http.client.HTTPMessage 的實(shí)例,帶有頭部各個(gè)字段,但不帶正文數(shù)據(jù)(與 HTTPResponse.msghttp.server.BaseHTTPRequestHandler.headers 一樣)。返回之后,文件指針 fp 已為讀取 HTTP 正文做好準(zhǔn)備了。

備注

parse_headers() 不會(huì)解析 HTTP 消息的開始行;只會(huì)解析各 Name: value 行。文件必須為讀取這些字段做好準(zhǔn)備,所以在調(diào)用該函數(shù)之前,第一行應(yīng)該已經(jīng)被讀取過了。

下列異常可以適當(dāng)?shù)乇灰l(fā):

exception http.client.HTTPException?

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

exception http.client.NotConnected?

HTTPException 的一個(gè)子類。

exception http.client.InvalidURL?

HTTPException 的一個(gè)子類,如果給出了一個(gè)非數(shù)字或?yàn)榭罩档亩丝诰蜁?huì)被引發(fā)。

exception http.client.UnknownProtocol?

HTTPException 的一個(gè)子類。

exception http.client.UnknownTransferEncoding?

HTTPException 的一個(gè)子類。

exception http.client.UnimplementedFileMode?

HTTPException 的一個(gè)子類。

exception http.client.IncompleteRead?

HTTPException 的一個(gè)子類。

exception http.client.ImproperConnectionState?

HTTPException 的一個(gè)子類。

exception http.client.CannotSendRequest?

ImproperConnectionState 的一個(gè)子類。

exception http.client.CannotSendHeader?

ImproperConnectionState 的一個(gè)子類。

exception http.client.ResponseNotReady?

ImproperConnectionState 的一個(gè)子類。

exception http.client.BadStatusLine?

HTTPException 的一個(gè)子類。 如果服務(wù)器反饋了一個(gè)我們不理解的 HTTP 狀態(tài)碼就會(huì)被引發(fā)。

exception http.client.LineTooLong?

HTTPException 的一個(gè)子類。 如果在 HTTP 協(xié)議中從服務(wù)器接收到過長(zhǎng)的行就會(huì)被引發(fā)。

exception http.client.RemoteDisconnected?

ConnectionResetErrorBadStatusLine 的一個(gè)子類。 當(dāng)嘗試讀取響應(yīng)時(shí)的結(jié)果是未從連接讀取到數(shù)據(jù)時(shí)由 HTTPConnection.getresponse() 引發(fā),表明遠(yuǎn)端已關(guān)閉連接。

3.5 新版功能: 在此之前引發(fā)的異常為 BadStatusLine('')。

此模塊中定義的常量為:

http.client.HTTP_PORT?

HTTP 協(xié)議默認(rèn)的端口號(hào) (總是 80)。

http.client.HTTPS_PORT?

HTTPS 協(xié)議默認(rèn)的端口號(hào) (總是 443)。

http.client.responses?

這個(gè)字典把 HTTP 1.1 狀態(tài)碼映射到 W3C 名稱。

例如:http.client.responses[http.client.NOT_FOUND]'NOT FOUND (未發(fā)現(xiàn))。

本模塊中可用的 HTTP 狀態(tài)碼常量可以參見 HTTP 狀態(tài)碼 。

HTTPConnection 對(duì)象?

HTTPConnection 實(shí)例擁有以下方法:

HTTPConnection.request(method, url, body=None, headers={}, *, encode_chunked=False)?

這會(huì)使用 HTTP 請(qǐng)求方法 method 和選擇器 url 向服務(wù)器發(fā)送請(qǐng)求。

如果給定 body,那么給定的數(shù)據(jù)會(huì)在信息頭完成之后發(fā)送。它可能是一個(gè) 字符串,一個(gè) bytes-like object,一個(gè)打開的 file object,或者 bytes 迭代器。如果 body 是字符串,它會(huì)按 HTTP 默認(rèn)的 ISO-8859-1 編碼。如果是一個(gè)字節(jié)類對(duì)象,它會(huì)按原樣發(fā)送。如果是 file object,文件的內(nèi)容會(huì)被發(fā)送,這個(gè)文件對(duì)象應(yīng)該至少支持``read()`` 方法。如果這個(gè)文件對(duì)象是一個(gè) io.TextIOBase 實(shí)例,由 read() 方法返回的數(shù)據(jù)會(huì)按 ISO-8859-1 編碼,否則由 read() 方法返回的數(shù)據(jù)會(huì)按原樣發(fā)送。如果 body 是一個(gè)迭代器,迭代器中的元素會(huì)被發(fā)送,直到迭代器耗盡。

headers 參數(shù)應(yīng)是額外的隨請(qǐng)求發(fā)送的 HTTP 信息頭的字典。

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

headers 中指定 Transfer-Encoding 時(shí), encode_chunked 是唯一相關(guān)的參數(shù)。如果 encode_chunkedFalse,HTTPConnection 對(duì)象會(huì)假定所有的編碼都由調(diào)用代碼處理。如果為 True,正文會(huì)按塊編碼。

備注

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

3.2 新版功能: body 現(xiàn)在可以是可迭代對(duì)象了。

在 3.6 版更改: 如果 Content-Length 和 Transfer-Encoding 都沒有在 headers 中設(shè)置,文件和可迭代的 body 對(duì)象現(xiàn)在會(huì)按塊編碼。添加了 encode_chunked 參數(shù)。不會(huì)嘗試去確定文件對(duì)象的 Content-Length。

HTTPConnection.getresponse()?

應(yīng)當(dāng)在發(fā)送一個(gè)請(qǐng)求從服務(wù)器獲取響應(yīng)時(shí)被調(diào)用。 返回一個(gè) HTTPResponse 的實(shí)例。

備注

請(qǐng)注意你必須在讀取了整個(gè)響應(yīng)之后才能向服務(wù)器發(fā)送新的請(qǐng)求。

在 3.5 版更改: 如果引發(fā)了 ConnectionError 或其子類, HTTPConnection 對(duì)象將在發(fā)送新的請(qǐng)求時(shí)準(zhǔn)備好重新連接。

HTTPConnection.set_debuglevel(level)?

設(shè)置調(diào)試等級(jí)。 默認(rèn)的調(diào)試等級(jí)為 0,意味著不會(huì)打印調(diào)試輸出。 任何大于 0 的值將使得所有當(dāng)前定義的調(diào)試輸出被打印到 stdout。 debuglevel 會(huì)被傳給任何新創(chuàng)建的 HTTPResponse 對(duì)象。

3.1 新版功能.

HTTPConnection.set_tunnel(host, port=None, headers=None)?

為 HTTP 連接隧道設(shè)置主機(jī)和端口。 這將允許通過代理服務(wù)器運(yùn)行連接。

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

headers 參數(shù)應(yīng)為一個(gè)隨 CONNECT 請(qǐng)求發(fā)送的額外 HTTP 標(biāo)頭的映射。

例如,要通過一個(gè)運(yùn)行于本機(jī) 8080 端口的 HTTPS 代理服務(wù)器隧道,我們應(yīng)當(dāng)向 HTTPSConnection 構(gòu)造器傳入代理的地址,并將我們最終想要訪問的主機(jī)地址傳給 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()?

當(dāng)對(duì)象被創(chuàng)建后連接到指定的服務(wù)器。 默認(rèn)情況下,如果客戶端還未建立連接,此函數(shù)會(huì)在發(fā)送請(qǐng)求時(shí)自動(dòng)被調(diào)用。

觸發(fā) 音頻事件 http.client.connect ,帶有 self 、host 、port 參數(shù)。

HTTPConnection.close()?

關(guān)閉到服務(wù)器的連接。

HTTPConnection.blocksize?

用于發(fā)送文件類消息體的緩沖區(qū)大小。

3.7 新版功能.

作為對(duì)使用上述 request() 方法的替代同,你也可以通過使用下面的四個(gè)函數(shù),分步驟發(fā)送請(qǐng)的請(qǐng)求。

HTTPConnection.putrequest(method, url, skip_host=False, skip_accept_encoding=False)?

應(yīng)為連接服務(wù)器之后首先調(diào)用的函數(shù)。將向服務(wù)器發(fā)送一行數(shù)據(jù),包含 method 字符串、url 字符串和 HTTP 版本(HTTP/1.1)。若要禁止自動(dòng)發(fā)送 Host:Accept-Encoding: 頭部信息(比如需要接受其他編碼格式的內(nèi)容),請(qǐng)將 skip_hostskip_accept_encoding 設(shè)為非 False 值。

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

向服務(wù)器發(fā)送一個(gè) RFC 822 格式的頭部。將向服務(wù)器發(fā)送一行由頭、冒號(hào)和空格以及第一個(gè)參數(shù)組成的數(shù)據(jù)。 如果還給出了其他參數(shù),將在后續(xù)行中發(fā)送,每行由一個(gè)制表符和一個(gè)參數(shù)組成。

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

向服務(wù)器發(fā)送一個(gè)空行,表示頭部文件結(jié)束。可選的 message_body 參數(shù)可用于傳入一個(gè)與請(qǐng)求相關(guān)的消息體。

如果 encode_chunkedTrue,則對(duì) message_body 的每次迭代結(jié)果將依照 RFC 7230 3.3.1 節(jié)的規(guī)范進(jìn)行分塊編碼。數(shù)據(jù)如何編碼取決于 message_body 的類型。 如果 message_body 實(shí)現(xiàn)了 buffer 接口,編碼將生成一個(gè)數(shù)據(jù)塊。如果 message_bodycollections.abc.Iterable,則 message_body 的每次迭代都會(huì)產(chǎn)生一個(gè)塊。 如果 message_bodyfile object,那么每次調(diào)用 .read() 都會(huì)產(chǎn)生一個(gè)數(shù)據(jù)塊。在 message_body 結(jié)束后,本方法立即會(huì)自動(dòng)標(biāo)記分塊編碼數(shù)據(jù)的結(jié)束。

備注

由于分塊編碼的規(guī)范要求,迭代器本身產(chǎn)生的空塊將被分塊編碼器忽略。這是為了避免目標(biāo)服務(wù)器因錯(cuò)誤編碼而過早終止對(duì)請(qǐng)求的讀取。

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

HTTPConnection.send(data)?

發(fā)送數(shù)據(jù)到服務(wù)器。本函數(shù)只應(yīng)在調(diào)用 endheaders() 方法之后且調(diào)用 getresponse() 之前直接調(diào)用。

觸發(fā) 音頻事件 http.client.send,參數(shù)為 self、data。

HTTPResponse 對(duì)象?

HTTPResponse 實(shí)例封裝了來(lái)自服務(wù)器的 HTTP 響應(yīng)。通過它可以訪問請(qǐng)求頭和響應(yīng)體。響應(yīng)是可迭代對(duì)象,可在 with 語(yǔ)句中使用。

在 3.5 版更改: 現(xiàn)在已實(shí)現(xiàn)了 io.BufferedIOBase 接口,并且支持所有的讀取操作。

HTTPResponse.read([amt])?

讀取并返回響應(yīng)體,或后續(xù) amt 個(gè)字節(jié)。

HTTPResponse.readinto(b)?

讀取響應(yīng)體的后續(xù) len(b) 個(gè)字節(jié)到緩沖區(qū) b。返回讀取的字節(jié)數(shù)。

3.3 新版功能.

HTTPResponse.getheader(name, default=None)?

返回頭部信息中的 name 值,如果沒有與 name 匹配的字段,則返回*default*。如果名為 name 的字段不止一個(gè),則返回所有字段,中間用 ', ' 連接。 如果 'default' 不是單個(gè)字符串,而是其他可迭代對(duì)象,則其元素同樣以逗號(hào)連接并返回。

HTTPResponse.getheaders()?

返回 (header, value) 元組構(gòu)成的列表。

HTTPResponse.fileno()?

返回底層套接字的 fileno。

HTTPResponse.msg?

包含響應(yīng)頭的 http.client.HTTPMessage 實(shí)例。http.client.HTTPMessageemail.message 的子類。

HTTPResponse.version?

服務(wù)器采用的 HTTP 協(xié)議版本。10 代表 HTTP/1.0,11 代表 HTTP/1.1。

HTTPResponse.url?

已讀取資源的 URL,通常用于確定是否進(jìn)行了重定向。

HTTPResponse.headers?

響應(yīng)的頭部信息,形式為 email.message.EmailMessage 的實(shí)例。

HTTPResponse.status?

由服務(wù)器返回的狀態(tài)碼。

HTTPResponse.reason?

服務(wù)器返回的原因短語(yǔ)。

HTTPResponse.debuglevel?

一個(gè)調(diào)試鉤子。如果 debuglevel 大于零,狀態(tài)信息將在讀取和解析響應(yīng)數(shù)據(jù)時(shí)打印輸出到 stdout。

HTTPResponse.closed?

如果流被關(guān)閉,則為``True``。

HTTPResponse.geturl()?

3.9 版后已移除: 已棄用,建議用 url。

HTTPResponse.info()?

3.9 版后已移除: 已棄用,建議用 headers。

HTTPResponse.getstatus()?

3.9 版后已移除: 已棄用,建議用 status

例子?

下面是使用 GET 方法的會(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ì)話示例。 請(qǐng)注意,HEAD 方法從不返回任何數(shù)據(jù)。

>>>
>>> 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ā)送請(qǐng)求的會(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()

在客戶端, HTTP PUT 請(qǐng)求與 POST 請(qǐng)求非常相似。區(qū)別只在于服務(wù)器端,HTTP 服務(wù)器將允許通過 PUT 請(qǐng)求創(chuàng)建資源。應(yīng)該注意的是,自定義的 HTTP 方法也可以在 urllib.request.Request 中通過設(shè)置適當(dāng)?shù)姆椒▽傩詠?lái)進(jìn)行處理。下面是一個(gè)會(huì)話示例,演示了如何利用 http.client 發(fā)送 PUT 請(qǐng)求。

>>>
>>> # 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 對(duì)象?

http.client.HTTPMessage 的實(shí)例存有 HTTP 響應(yīng)的頭部信息。利用 email.message.Message 類實(shí)現(xiàn)。