python3从零学习-5.10.8、http.client-HTTP协议客户端

源代码: Lib/http/client.py

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

注解 : HTTPS 支持仅在编译 Python 时启用了 SSL 支持的情况下(通过 ssl 模块)可用。

该模块支持以下类:

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

HTTPConnection实例表示一个使用HTTP服务器的事务。应该实例化它,向它传递主机和可选端口号。如果没有传递端口号,则从主机字符串中提取端口(如果它具有form host:port),否则使用缺省HTTP端口(80)。如果给定了可选的超时参数,那么阻塞操作(如连接尝试)将在那么多秒后超时(如果没有给定,则使用全局默认超时设置)。可选的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_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.6 版后已移除: key_file 和 cert_file 已弃用并转而推荐 context。 请改用 ssl.SSLContext.load_cert_chain() 或让 ssl.create_default_context() 为你选择系统所信任的 CA 证书。

check_hostname 参数也已弃用;应当改用 context 的 ssl.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

ConnectionResetError 和 BadStatusLine 的一个子类。 当尝试读取响应时的结果是未从连接读取到数据时由 HTTPConnection.getresponse() 引发,表明远端已关闭连接。

此模块中定义的常量为:

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 (未发现)。

HTTPConnection 对象

HTTPConnection 实例拥有以下方法:

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

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

如果给定 body,那么给定的数据会在信息头完成之后发送。它可能是一个 str 、一个 bytes-like object 、一个打开的 file object,或者 bytes 迭代器。如果 body 是字符串,它会按 HTTP 默认的 ISO-8859-1 编码;如果是一个字节类对象,它会按原样发送;如果是 file object ,文件的内容会被发送,这个文件对象应该支持 read() 方法。如果这个文件对象是一个 io.TextIOBase 实例, read() 方法返回的数据会按 ISO-8859-1 编码,否则 read() 方法返回的数据会按原样发送;如果 body 是一个迭代器,迭代器中的元素会被发送,直到迭代器耗尽。

headers 参数应是额外的随请求发送的 HTTP 信息头的字典。

如果 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,正文会按块编码。

注解 HTTP 协议在 1.1 版中添加了块传输编码。除非明确知道 HTTP 服务器可以处理 HTTP 1.1,调用者要么必须指定 Content-Length,要么必须传入 str 或字节类对象,注意该对象不能是表达 body 的文件。

3.2 新版功能: body 现在可以是可迭代对象了。

在 3.6 版更改: 如果 Content-Length 和 Transfer-Encoding 都没有在 headers 中设置,文件和可迭代的 body 对象现在会按块编码。添加了 encode_chunked 参数。不会尝试去确定文件对象的 Content-Length。

HTTPConnection.getresponse()

应当在发送一个请求从服务器获取响应时被调用。 返回一个 HTTPResponse 的实例。

注解 请注意你必须在读取了整个响应之后才能向服务器发送新的请求。

在 3.5 版更改: 如果引发了 ConnectionError 或其子类, HTTPConnection 对象将在发送新的请求时准备好重新连接。

HTTPConnection.set_debuglevel(level)

设置调试等级。 默认的调试等级为 0,意味着不会打印调试输出。 任何大于 0 的值将使得所有当前定义的调试输出被打印到 stdout。 debuglevel 会被传给任何新创建的 HTTPResponse 对象。

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

为 HTTP 连接隧道设置主机和端口。 这将允许通过代理服务器运行连接。

host 和 port 参数指明隧道连接的位置(即 CONNECT 请求所包含的地址,而 不是 代理服务器的地址)。

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

HTTPConnection.connect()

当对象被创建后连接到指定的服务器。 默认情况下,如果客户端还未建立连接,此函数会在发送请求时自动被调用。

HTTPConnection.close()

关闭到服务器的连接。

作为对使用上述 request() 方法的替代同,你也可以通过使用下面的四个函数,分步骤发送请的请求。

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

这应该是连接到服务器后的第一次调用。它向服务器发送一行代码,包括方法字符串、url字符串和HTTP版本(HTTP/1.1)。要禁用Host:或accept - encoding:头的自动发送(例如接受额外的内容编码),请使用非假值指定skip_host或skip_accept_encoding。

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

发送一个RFC 822样式的头到服务器。它向服务器发送一行代码,包括标题、冒号、空格和第一个参数。如果给出更多的参数,则发送延续行,每一行由一个制表符和一个参数组成。

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

向服务器发送一个空行,表示标头的结束。可选的message_body参数可用于传递与请求关联的消息体。

如果encode_chunked为真,则message_body的每次迭代的结果将按照RFC 7230第3.3.1节的规定进行块编码。数据的编码方式取决于message_body的类型。如果message_body实现了缓冲区接口,那么编码将产生单个块。如果message_body是一个集合。可迭代的,message_body的每次迭代都会产生一个块。如果message_body是一个文件对象,那么每次对.read()的调用都会产生一个块。该方法会立即在message_body之后自动发出块编码数据的结束信号。

HTTPConnection.send(data)

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

HTTPResponse 对象

HTTPResponse实例包装来自服务器的HTTP响应。它提供对请求头和实体主体的访问。响应是一个可迭代对象,可以在with语句中使用。

在3.5版更改:io。BufferedIOBase接口现在已经实现,并且支持它的所有读取器操作。

HTTPResponse.read([amt])

读取并返回响应体,或者一直到下一个amt字节。

HTTPResponse.readinto(b)

将响应体的下一个len(b)字节读入缓冲区b。返回读取的字节数。

HTTPResponse.getheader(name, default=None)

返回标题名称的值,如果没有标题匹配名称,则返回默认值。如果名称名为name的头部超过一个,则返回由,连接的所有值。如果‘default’是除单个字符串之外的任何可迭代的字符串,其元素也会以逗号连接返回。

HTTPResponse.getheaders()

返回元组(头、值)列表。

HTTPResponse.fileno()

返回基础套接字的文件名。

HTTPResponse.msg

http.client。包含响应头的HTTPMessage实例。http.client。HTTPMessage是email.message.Message的子类。

HTTPResponse.version

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

HTTPResponse.status

由服务器返回的状态码。

HTTPResponse.reason

由服务器返回的原因短语。

HTTPResponse.debuglevel

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

HTTPResponse.closed

如果流关闭,则为真。

例子

下面是一个使用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 bRedirecting to <a href=""></a> >>> conn.close()

客户端HTTP PUT请求与POST请求非常相似。区别仅在于服务器端,其中HTTP服务器将允许通过PUT请求创建资源。需要注意的是,定制HTTP方法+也在urllib.request中被处理。通过发送适当的+方法属性来请求。下面是一个示例会话,展示了如何使用http.client执行PUT请求:

>>> # with the content of BODY as the enclosed representation >>> # for the resource :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