http.client
— HTTP 协议客户端¶
源代码: Lib/http/client.py
此模块定义了实现 HTTP 和 HTTPS 协议客户端的类。它通常不直接使用 — 模块 urllib.request
使用它来处理使用 HTTP 和 HTTPS 的 URL。
另请参阅
推荐使用 Requests 包 作为更高级别的 HTTP 客户端接口。
注意
仅当 Python 使用 SSL 支持编译(通过 ssl
模块)时,才支持 HTTPS。
可用性:不支持 Emscripten,不支持 WASI。
此模块在 WebAssembly 平台 wasm32-emscripten
和 wasm32-wasi
上不可用或无法工作。有关更多信息,请参阅 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 选项的ssl.SSLContext
实例。有关最佳实践的更多信息,请阅读 安全注意事项。
在 3.2 版更改: 添加了 source_address、context 和 check_hostname。
在 3.2 版更改: 如果可能(即,如果
ssl.HAS_SNI
为真),此类现在支持 HTTPS 虚拟主机。在 3.4 版更改: 删除了 strict 参数。不再支持 HTTP 0.9 风格的“简单响应”。
在 3.4.3 版更改: 此类现在默认执行所有必要的证书和主机名检查。要恢复到以前的未经验证的行为,可以将
ssl._create_unverified_context()
传递给 context 参数。在 3.8 版更改: 此类现在为默认 context 或在使用自定义 context 传递 cert_file 时启用 TLS 1.3
ssl.SSLContext.post_handshake_auth
。在 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
行。该文件必须准备好读取这些字段行,因此在调用该函数之前,应该已经读取了第一行。
将根据情况引发以下异常
- 异常 http.client.NotConnected¶
HTTPException
的子类。
- 异常 http.client.InvalidURL¶
HTTPException
的子类,如果给定的端口是非数字或为空,则会引发此异常。
- 异常 http.client.UnknownProtocol¶
HTTPException
的子类。
- 异常 http.client.UnknownTransferEncoding¶
HTTPException
的子类。
- 异常 http.client.UnimplementedFileMode¶
HTTPException
的子类。
- 异常 http.client.IncompleteRead¶
HTTPException
的子类。
- 异常 http.client.ImproperConnectionState¶
HTTPException
的子类。
- 异常 http.client.CannotSendRequest¶
- 异常 http.client.CannotSendHeader¶
- 异常 http.client.ResponseNotReady¶
- 异常 http.client.BadStatusLine¶
HTTPException
的子类。如果服务器响应我们无法理解的 HTTP 状态代码,则会引发此异常。
- 异常 http.client.LineTooLong¶
HTTPException
的子类。如果从服务器收到的 HTTP 协议中的行过长,则会引发此异常。
- 异常 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.pythonlang.cn/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。这允许连接通过代理服务器运行。
host 和 port 参数指定隧道连接的端点(即 CONNECT 请求中包含的地址, *而不是* 代理服务器的地址)。
headers 参数应该是要随 CONNECT 请求一起发送的额外 HTTP 标头的映射。
由于 HTTP/1.1 用于 HTTP CONNECT 隧道请求,根据 RFC,必须提供 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()¶
连接到对象创建时指定的服务器。默认情况下,如果客户端还没有连接,则在发出请求时会自动调用此方法。
使用参数
self
、host
、port
引发带有参数的 审计事件http.client.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:
标头(例如,要接受其他内容编码),请使用非 False 值指定 skip_host 或 skip_accept_encoding。
- 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()
之前,才应该直接使用此方法。使用参数
self
、data
引发 审计事件http.client.send
。
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 协议版本。10 表示 HTTP/1.0,11 表示 HTTP/1.1。
- HTTPResponse.url¶
检索到的资源的 URL,通常用于确定是否进行了重定向。
- HTTPResponse.headers¶
以
email.message.EmailMessage
实例形式的响应头。
- HTTPResponse.status¶
服务器返回的状态码。
- HTTPResponse.reason¶
服务器返回的原因短语。
- HTTPResponse.debuglevel¶
调试钩子。如果
debuglevel
大于零,则在读取和解析响应时,消息将打印到标准输出。
- 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 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 对象¶
- class http.client.HTTPMessage(email.message.Message)¶
http.client.HTTPMessage
实例保存 HTTP 响应中的标头。它是使用 email.message.Message
类实现的。