Skip to main content

21.12. http.client — HTTP协议客户端

源代码: Lib/http/client.py


此模块定义实现HTTP和HTTPS协议的客户端端的类。它通常不直接使用 - 模块 urllib.request 使用它来处理使用HTTP和HTTPS的URL。

参见

建议将 请求包 用于更高级别的HTTP客户端接口。

注解

HTTPS支持仅在Python通过SSL支持(通过 ssl 模块)进行编译时可用。

该模块提供以下类:

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

HTTPConnection 实例表示与HTTP服务器的一个事务。应该实例化它传递一个主机和可选的端口号。如果没有通过端口号,则从主机字符串中提取端口,如果格式为 host:port,否则使用默认HTTP端口(80)。如果给出了可选的 timeout 参数,阻塞操作(如连接尝试)将在该秒数后超时(如果未给出,则使用全局默认超时设置)。可选的 source_address 参数可以是用作从其进行HTTP连接的源地址的(主机,端口)的元组。

例如,以下调用都将创建在同一主机和端口连接到服务器的实例:

>>> 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样式的“简单响应”。

class http.client.HTTPSConnection(host, port=None, key_file=None, cert_file=None, [timeout, ]source_address=None, *, context=None, check_hostname=None)

HTTPConnection 的子类,使用SSL与安全服务器通信。默认端口为 443。如果指定了 context,它必须是描述各种SSL选项的 ssl.SSLContext 实例。

有关最佳做法的更多信息,请阅读 安全注意事项

在 3.2 版更改: source_addresscontextcheck_hostname

在 3.2 版更改: 如果可能,此类现在支持HTTPS虚拟主机(即,如果 ssl.HAS_SNI 为true)。

在 3.4 版更改: strict 参数已删除。不再支持HTTP 0.9样式的“简单响应”。

在 3.4.3 版更改: 默认情况下,此类现在执行所有必需的证书和主机名检查。要恢复到上一个未验证的行为,ssl._create_unverified_context() 可以传递给 context 参数。

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状态代码 作为常量。

21.12.1. HTTPConnection对象

HTTPConnection 实例有以下方法:

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

这将使用HTTP请求方法 method 和选择器 url 向服务器发送请求。

如果指定了 body,则在标题完成后发送指定的数据。它可以是 strbytes-like object,开放 file object 或可重复的 bytes。如果 body 是字符串,则将其编码为ISO-8859-1,HTTP的默认值。如果它是一个类似字节的对象,字节是按原样发送的。如果是 file object,则发送文件的内容;这个文件对象应该至少支持 read() 方法。如果文件对象是 io.TextIOBase 的实例,则 read() 方法返回的数据将被编码为ISO-8859-1,否则 read() 返回的数据将按原样发送。如果 body 是可迭代的,则可迭代的元素按原样发送,直到可迭代被耗尽。

headers 参数应该是与请求一起发送的额外HTTP头的映射。

如果 headers 既不包含Content-Length也不包含传输编码,但是有一个请求体,那么这些头字段之一将被自动添加。如果 bodyNone,则对于期望主体(PUTPOSTPATCH)的方法,将Content-Length头设置为 0。如果 body 是不是 文件 的字符串或类似字节的对象,则将Content-Length头设置为其长度。任何其他类型的 body (一般为文件和迭代器)将被块编码,并且将自动设置Transfer-Encoding头,而不是Content-Length。

仅当在 headers 中指定传输编码时,encode_chunked 参数才相关。如果 encode_chunkedFalse,则HTTPConnection对象假定所有编码由调用代码处理。如果它是 True,主体将被块编码。

注解

分块传输编码已添加到HTTP协议版本1.1。除非知道HTTP服务器处理HTTP 1.1,否则调用者必须指定Content-Length,或者必须传递一个 str 或类似字节的对象,它不是一个文件作为主体表示。

3.2 新版功能: body 现在可以是一个迭代。

在 3.6 版更改: 如果在 headers 中既没有设置Content-Length也没有设置传输编码,则文件和可迭代的 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隧道的主机和端口。这允许通过代理服务器运行连接。

主机和端口参数指定隧道连接的端点(即包含在CONNECT请求中的地址,not 代理服务器的地址)。

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()

关闭与服务器的连接。

作为使用上述 request() 方法的替代方法,您还可以通过使用以下四个函数逐步发送请求。

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

这应该是在连接到服务器之后的第一个调用。它向由 method 字符串,url 字符串和HTTP版本(HTTP/1.1)组成的服务器发送一行。要禁用 Host:Accept-Encoding: 头的自动发送(例如,要接受其他内容编码),请指定具有非False值的 skip_hostskip_accept_encoding

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

向服务器发送 RFC 822 -style头。它发送一条线到服务器,包括头,冒号和空格,以及第一个参数。如果给出更多的参数,则发送连续行,每行由一个制表符和一个参数组成。

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

发送空白行到服务器,用信号通知头的结束。可选的 message_body 参数可用于传递与请求相关联的消息体。

如果 encode_chunkedTrue,则 message_body 的每次迭代的结果将按照 RFC 7230 第3.3.1节中的规定进行块编码。数据如何编码取决于 message_body 的类型。如果 message_body 实现 缓冲接口,编码将导致单个块。如果 message_bodycollections.Iterable,则 message_body 的每次迭代将产生一个块。如果 message_bodyfile object,则对 .read() 的每次调用都将产生一个块。该方法在 message_body 之后立即自动发信号通知块编码数据的结束。

注解

由于分块编码规范,迭代器主体产生的空块将被块编码器忽略。这是为了避免由于格式不正确的编码而导致目标服务器读取请求的过早终止。

3.6 新版功能: 分块编码支持。添加了 encode_chunked 参数。

HTTPConnection.send(data)

将数据发送到服务器。只有在调用 endheaders() 方法之后和在调用 getresponse() 之前,才应该直接使用此方法。

21.12.2. 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()

返回(标题,值)元组的列表。

HTTPResponse.fileno()

返回底层套接字的 fileno

HTTPResponse.msg

包含响应标头的 http.client.HTTPMessage 实例。 http.client.HTTPMessageemail.message.Message 的一个子类。

HTTPResponse.version

服务器使用的HTTP协议版本。 10用于HTTP/1.0,11用于HTTP/1.1。

HTTPResponse.status

服务器返回的状态代码。

HTTPResponse.reason

服务器返回的原因短语。

HTTPResponse.debuglevel

调试挂钩。如果 debuglevel 大于零,则响应被读取和解析时,消息将被打印到stdout。

HTTPResponse.closed

如果流已关闭,则为 True

21.12.3. 例子

下面是使用 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 not r1.closed:
...     print(r1.read(200))  # 200 bytes
b'<!doctype html>\n<!--[if"...
...
>>> # Example of an invalid request
>>> 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

21.12.4. HTTPMessage对象

http.client.HTTPMessage 实例保存来自HTTP响应的头。它使用 email.message.Message 类实现。