http.client
— HTTP 协议客户端¶
源代码: Lib/http/client.py
此模块定义了实现 HTTP 和 HTTPS 协议客户端的类。 它通常不直接使用 — 模块 urllib.request
使用它来处理使用 HTTP 和 HTTPS 的 URL。
参见
建议使用 Requests 包 来获得更高级别的 HTTP 客户端接口。
备注
只有在 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 选项的ssl.SSLContext
实例。请阅读 安全注意事项 以获取有关最佳实践的更多信息。
在 3.2 版本中更改: 添加了 *source_address*、*context* 和 *check_hostname*。
在 3.2 版本中更改: 如果可能(即,如果
ssl.HAS_SNI
为 true),此类现在支持 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
行。该文件必须准备好读取这些字段行,因此在调用该函数之前应已消耗第一行。
根据需要引发以下异常
- exception 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¶
是
ImproperConnectionState
的子类。
- 异常 http.client.CannotSendHeader¶
是
ImproperConnectionState
的子类。
- 异常 http.client.ResponseNotReady¶
是
ImproperConnectionState
的子类。
- 异常 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。只有在 headers 中指定了 Transfer-Encoding 时,encode_chunked 参数才相关。 如果 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
或类似字节的对象(而不是文件)作为 body 的表示。在 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 参数应该是一个额外的 HTTP 标头映射,用于随 CONNECT 请求一起发送。
由于 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()¶
连接到创建对象时指定的服务器。默认情况下,如果客户端尚未建立连接,则在发出请求时会自动调用此方法。
引发一个 审计事件
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()
之前,才应直接使用此方法。引发带有参数
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 协议版本。 HTTP/1.0 为 10,HTTP/1.1 为 11。
- 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
请求创建资源。 应当注意的是,通过设置适当的方法属性,也可以在 urllib.request.Request
中处理自定义 HTTP 方法。 这是一个使用 PUT
方法的会话示例
>>> # This creates an HTTP request
>>> # with the content of BODY as the enclosed representation
>>> # for the resource https://127.0.0.1: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
类实现。