http.client — HTTP 协议 Client 端

源代码: Lib/http/client.py


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

See also

推荐使用Requests package作为更高级别的 HTTPClient 端界面。

Note

仅当 Python 使用 SSL 支持(passssl模块)编译时,HTTPS 支持才可用。

该模块提供以下类:

    • class * http.client. HTTPConnection(* host port = None *,[* timeout *,] * source_address = None blocksize = 8192 *)
    • HTTPConnection实例代表与 HTTP 服务器的一笔 Transaction。应该实例化它,并为其传递主机和可选端口号。如果未传递任何端口号,则如果端口的格式为host:port,则将从主机字符串中提取该端口,否则将使用默认的 HTTP 端口(80)。如果给出了可选的* timeout 参数,则阻塞操作(如连接try)将在几秒钟后超时(如果未给出,则使用全局默认超时设置)。可选的 source_address 参数可以是(主机,端口)的 Tuples,用作构建 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 key_file = None cert_file = None ,[* timeout *,] * source_address = None **, context = None *, * check_hostname = None blocksize = 8192 *)
    • HTTPConnection的子类,它使用 SSL 与安全服务器进行通信。默认端口为443。如果指定了* context *,则它必须是ssl.SSLContext实例,用于描述各种 SSL 选项。

请阅读Security considerations以获取有关最佳做法的更多信息。

在 3.2 版中进行了更改:添加了* source_address context check_hostname *。

在版本 3.2 中进行了更改:此类现在尽可能支持 HTTPS 虚拟主机(即ssl.HAS_SNI为 true)。

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

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

在版本 3.8 中更改:此类现在为默认* context 或pass自定义 context 传递 cert_file *时启用 TLS 1.3 ssl.SSLContext.post_handshake_auth

自 3.6 版起不推荐使用:* key_file cert_file 不再推荐使用 context *。请改用ssl.SSLContext.load_cert_chain(),或让ssl.create_default_context()为您选择系统的受信任 CA 证书。

    • class * http.client. HTTPResponse(* sock debuglevel = 0 method = None url = None *)
    • 成功连接后返回其实例的类。不能直接由用户实例化。

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

该模块提供以下Function:

  • http.client. parse_headers(* fp *)
    • 从表示 HTTP 请求/响应的文件指针* fp *解析 Headers。该文件必须是BufferedIOBase阅读器(即不是文本),并且必须提供有效的 RFC 2822样式标题。

此函数返回http.client.HTTPMessage的实例,该实例保存 Headers 字段,但没有有效载荷(与HTTPResponse.msghttp.server.BaseHTTPRequestHandler.headers相同)。返回后,文件指针* fp *准备读取 HTTP 正文。

Note

parse_headers()不解析 HTTP 消息的起始行;它只解析Name: value行。该文件必须已准备好读取这些字段行,因此在调用该函数之前,第一行应已被使用。

适当地提出了以下异常:

  • exception http.client. HTTPException

    • 此模块中其他异常的 Base Class。它是Exception的子类。
  • exception http.client. NotConnected

  • exception http.client. InvalidURL

    • HTTPException的子类,如果提供了端口,则为非数字或为空,则引发。
  • exception http.client. UnknownProtocol

  • exception http.client. UnknownTransferEncoding

  • exception http.client. UnimplementedFileMode

  • exception http.client. IncompleteRead

  • exception http.client. ImproperConnectionState

  • exception http.client. CannotSendRequest

  • exception http.client. CannotSendHeader

  • exception http.client. ResponseNotReady

  • exception http.client. BadStatusLine

    • HTTPException的子类。如果服务器使用我们不理解的 HTTP 状态代码响应,则引发。
  • exception http.client. LineTooLong

    • HTTPException的子类。如果从服务器以 HTTP 协议接收到过长的行,则引发。
  • exception http.client. RemoteDisconnected

版本 3.5 的新Function:以前曾提出BadStatusLine ('')

此模块中定义的常量为:

  • http.client. HTTP_PORT

    • HTTP 协议的默认端口(始终为80)。
  • http.client. HTTPS_PORT

    • HTTPS 协议的默认端口(始终为443)。
  • http.client. responses

    • 该词典将 HTTP 1.1 状态代码 Map 到 W3C 名称。

示例:http.client.responses[http.client.NOT_FOUND]'Not Found'

有关可在此模块中用作常量的 HTTP 状态代码列表,请参见HTTP 状态码

HTTPConnection Objects

HTTPConnection个实例具有以下方法:

  • HTTPConnection. request(方法,* url body = None headers ={} **,* encode_chunked = False *)
    • 这将使用 HTTP 请求方法* method 和 selectors url *向服务器发送请求。

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

  • headers *参数应该是与请求一起发送的额外 HTTPHeaders 的 Map。

如果* headers 既不包含 Content-Length 也不包含 Transfer-Encoding,但是有一个请求正文,则这些 header 字段之一将被自动添加。如果 body None,则对于需要主体(PUTPOSTPATCH)的方法,Content-LengthHeaders 设置为0。如果 body 是不是file的字符串或类似字节的对象,则将 Content-LengthHeaders 设置为其长度。任何其他类型的 body *(通常是文件和可迭代对象)都将进行块编码,并且将自动设置 Transfer-EncodingHeaders,而不是 Content-Length。

只有在* headers 中指定了 Transfer-Encoding 时, encode_chunked 参数才有意义。如果 encode_chunked *为False,则 HTTPConnection 对象假定所有编码均由调用代码处理。如果为True,则主体将进行块编码。

Note

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

3.2 版中的新Function:* body *现在可以迭代。

在版本 3.6 中更改:现在,如果* headers 中未设置 Content-Length 和 Transfer-Encoding,则 file 和可迭代的 body *对象现在将进行块编码。 * encode_chunked *参数已添加。没有try确定文件对象的 Content-Length。

  • HTTPConnection. getresponse ( )
    • 发送请求以从服务器获取响应后应调用该方法。返回一个HTTPResponse实例。

Note

请注意,您必须先阅读整个响应,然后才能向服务器发送新请求。

在版本 3.5 中进行了更改:如果引发了ConnectionError或子类,则在发送新请求时HTTPConnection对象将准备重新连接。

  • HTTPConnection. set_debuglevel(级别)
    • 设置调试级别。默认的调试级别是0,这意味着没有打印调试输出。任何大于0的值都将导致所有当前定义的调试输出被打印到 stdout。 debuglevel传递给创建的任何新的HTTPResponse对象。

3.1 版中的新Function。

  • HTTPConnection. set_tunnel(* host port = None headers = None *)
    • 设置 HTTP 连接隧道的主机和端口。这允许pass代理服务器运行连接。

host 和 port 参数指定隧道连接的端点(即 CONNECT 请求中包含的地址,不是代理服务器的地址)。

headers 参数应该是要与 CONNECT 请求一起发送的额外 HTTPHeaders 的 Map。

例如,要pass本地运行在端口 8080 上的 HTTPS 代理服务器构建隧道,我们会将代理的地址传递给HTTPSConnection构造函数,并将我们finally想要到达的主机的地址传递给set_tunnel()方法:

>>> import http.client
>>> conn = http.client.HTTPSConnection("localhost", 8080)
>>> conn.set_tunnel("www.python.org")
>>> conn.request("HEAD","/index.html")

3.2 版中的新Function。

  • HTTPConnection. connect ( )

    • 连接到创建对象时指定的服务器。默认情况下,如果 Client 端尚未构建连接,则在发出请求时会自动调用此方法。
  • HTTPConnection. close ( )

    • 关闭与服务器的连接。
  • HTTPConnection. blocksize

    • 用于发送类似文件的消息正文的缓冲区大小(以字节为单位)。

3.7 版中的新Function。

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

  • HTTPConnection. putrequest(方法,* url skip_host = False skip_accept_encoding = False *)

    • 这应该是与服务器构建连接后的第一个呼叫。它向服务器发送一条由* method 字符串, url 字符串和 HTTP 版本(HTTP/1.1)组成的行。要禁用自动发送Host:Accept-Encoding:Headers(例如,接受其他内容编码),请使用非 False 值指定 skip_host skip_accept_encoding *。
  • HTTPConnection. putheader(* header argument * [,* ... *])

    • RFC 822样式的 Headers 发送到服务器。它向服务器发送一条由标题,冒号和空格以及第一个参数组成的行。如果给出更多的参数,则发送连续行,每行包括一个制表符和一个参数。
  • HTTPConnection. endheaders(* message_body = None **,* encode_chunked = False *)

    • 向服务器发送空白行,以指示 Headers 的末尾。可选的* message_body *参数可用于传递与请求关联的消息正文。

如果* encode_chunked True,则 message_body 的每次迭代的结果将按照 RFC 7230第 3.3.1 节中的指定进行块编码。数据的 encodings 取决于 message_body 的类型。如果 message_body 实现buffer interface,则编码将导致单个块。如果 message_body collections.abc.Iterable,则 message_body 的每次迭代都会产生一个块。如果 message_body file object,则每次对.read()的调用都会产生一个块。该方法会在 message_body *之后立即自动发 signal 通知块编码数据的结尾。

Note

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

3.6 版的新Function:块编码支持。 * encode_chunked *参数已添加。

  • HTTPConnection. send(* data *)

HTTPResponse Objects

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

在版本 3.5 中进行了更改:现已实现io.BufferedIOBase接口,并且支持其所有读取器操作。

  • HTTPResponse. read([* amt *])

    • 读取并返回响应正文,或直至下一个* amt *字节。
  • HTTPResponse. readinto(* b *)

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

版本 3.3 中的新Function。

  • HTTPResponse. getheader(* name default = None *)

    • 返回 Headers* name 的值;如果没有与 Headers name 匹配的 Headers,则返回 default 。如果有多个标题为 name *的 Headers,则返回所有以','连接的值。如果'default'是除单个字符串之外的任何可迭代对象,则类似地返回其元素并以逗号连接。
  • HTTPResponse. getheaders ( )

    • 返回(头,值)Tuples 的列表。
  • HTTPResponse. fileno ( )

    • 返回基础套接字的fileno
  • HTTPResponse. msg

    • 包含响应 Headers 的http.client.HTTPMessage实例。 http.client.HTTPMessageemail.message.Message的子类。
  • HTTPResponse. version

    • 服务器使用的 HTTP 协议版本。 HTTP/1.0 为 10,HTTP/1.1 为 11.
  • HTTPResponse. status

    • 服务器返回的状态码。
  • HTTPResponse. reason

    • 服务器返回的原因短语。
  • HTTPResponse. debuglevel

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

    • 如果流关闭,则为True

Examples

这是使用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="http://bugs.python.org/issue12524">http://bugs.python.org/issue12524</a>'
>>> conn.close()

Client 端HTTP PUT请求与POST请求非常相似。区别仅在于服务器端,HTTP 服务器将允许passPUT请求创建资源。应该注意的是,pass设置适当的 method 属性,在urllib.request.Request中也可以处理自定义 HTTP 方法。这是一个示例会话,显示了如何使用 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

HTTPMessage Objects

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