目录
源代码: 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.NotConnectedHTTPException 的一个子类。
exception http.client.InvalidURLHTTPException 的一个子类,如果给出了一个非数字或为空值的端口就会被引发。
exception http.client.UnknownProtocolHTTPException 的一个子类。
exception http.client.UnknownTransferEncodingHTTPException 的一个子类。
exception http.client.UnimplementedFileModeHTTPException 的一个子类。
exception http.client.IncompleteReadHTTPException 的一个子类。
exception http.client.ImproperConnectionStateHTTPException 的一个子类。
exception http.client.CannotSendRequestImproperConnectionState 的一个子类。
exception http.client.CannotSendHeaderImproperConnectionState 的一个子类。
exception http.client.ResponseNotReadyImproperConnectionState 的一个子类。
exception http.client.BadStatusLineHTTPException 的一个子类。 如果服务器反馈了一个我们不理解的 HTTP 状态码就会被引发。
exception http.client.LineTooLongHTTPException 的一个子类。 如果在 HTTP 协议中从服务器接收到过长的行就会被引发。
exception http.client.RemoteDisconnectedConnectionResetError 和 BadStatusLine 的一个子类。 当尝试读取响应时的结果是未从连接读取到数据时由 HTTPConnection.getresponse() 引发,表明远端已关闭连接。
此模块中定义的常量为:
http.client.HTTP_PORTHTTP 协议默认的端口号 (总是 80)。
http.client.HTTPS_PORTHTTPS 协议默认的端口号 (总是 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