python standard library http

python 标准库之 http

山雨欲来风满楼,最近不是很太平,希望世界和平吧。

python 标准库学习 之 http

http 是一个包,它收集了多个用于处理超文本传输协议的模块:

参考文档

本次只整理 http.client的内容,后面持续更新。

常量

class http.HTTPStatus

使用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> from http import HTTPStatus
>>> HTTPStatus.OK
<HTTPStatus.OK: 200>
>>> HTTPStatus.OK == 200
True
>>> HTTPStatus.OK.value
200
>>> HTTPStatus.OK.phrase
'OK'
>>> HTTPStatus.OK.description
'Request fulfilled, document follows'
>>> list(HTTPStatus)
[<HTTPStatus.CONTINUE: 100>, <HTTPStatus.SWITCHING_PROTOCOLS: 101>, ...]

HTTP状态码

状态码 映射名 详情
100 CONTINUE HTTP/1.1 RFC 7231, 6.2.1 节
101 SWITCHING_PROTOCOLS HTTP/1.1 RFC 7231, 6.2.2 节
102 PROCESSING WebDAV RFC 2518, 10.1 节
200 OK HTTP/1.1 RFC 7231, 6.3.1 节
201 CREATED HTTP/1.1 RFC 7231, 6.3.2 节
202 ACCEPTED HTTP/1.1 RFC 7231, 6.3.3 节
203 NON_AUTHORITATIVE_INFORMATION HTTP/1.1 RFC 7231, 6.3.4 节
204 NO_CONTENT HTTP/1.1 RFC 7231, 6.3.5 节
205 RESET_CONTENT HTTP/1.1 RFC 7231, 6.3.6 节
206 PARTIAL_CONTENT HTTP/1.1 RFC 7233, 4.1 节
207 MULTI_STATUS WebDAV RFC 4918, 11.1 节
208 ALREADY_REPORTED WebDAV Binding Extensions RFC 5842, 7.1 节(实验性)
226 IM_USED Delta Encoding in HTTP RFC 3229, 10.4.1 节
300 MULTIPLE_CHOICES:有多种资源可选择 HTTP/1.1 RFC 7231, 6.4.1 节
301 MOVED_PERMANENTLY:永久移动 HTTP/1.1 RFC 7231, 6.4.2 节
302 FOUND:临时移动 HTTP/1.1 RFC 7231, 6.4.3 节
303 SEE_OTHER:已经移动 HTTP/1.1 RFC 7231, 6.4.4 节
304 NOT_MODIFIED:没有修改 HTTP/1.1 RFC 7232, 4.1 节
305 USE_PROXY:使用代理 HTTP/1.1 RFC 7231, 6.4.5 节
307 TEMPORARY_REDIRECT:临时重定向 HTTP/1.1 RFC 7231, 6.4.7 节
308 PERMANENT_REDIRECT:永久重定向 Permanent Redirect RFC 7238, Section 3 (Experimental)
400 BAD_REQUEST:错误请求 HTTP/1.1 RFC 7231, 6.5.1 节
401 UNAUTHORIZED:未授权 HTTP/1.1 Authentication RFC 7235, 3.1 节
402 PAYMENT_REQUIRED:保留,将来使用 HTTP/1.1 RFC 7231, 6.5.2 节
403 FORBIDDEN:禁止 HTTP/1.1 RFC 7231, 6.5.3 节
404 NOT_FOUND:没有找到 HTTP/1.1 RFC 7231, 6.5.4 节
405 METHOD_NOT_ALLOWED:该请求方法不允许 HTTP/1.1 RFC 7231, 6.5.5 节
406 NOT_ACCEPTABLE:不可接受 HTTP/1.1 RFC 7231, 6.5.6 节
407 PROXY_AUTHENTICATION_REQUIRED:要求使用代理验证身份 HTTP/1.1 Authentication RFC 7235, 3.1 节
408 REQUEST_TIMEOUT:请求超时 HTTP/1.1 RFC 7231, 6.5.7 节
409 CONFLICT:冲突 HTTP/1.1 RFC 7231, 6.5.8 节
410 GONE:已经不在了 HTTP/1.1 RFC 7231, 6.5.9 节
411 LENGTH_REQUIRED:长度要求 HTTP/1.1 RFC 7231, 6.5.10 节
412 PRECONDITION_FAILED:前提条件错误 HTTP/1.1 RFC 7232, 4.2 节
413 REQUEST_ENTITY_TOO_LARGE:请求体太大了 HTTP/1.1 RFC 7231, 6.5.11 节
414 REQUEST_URI_TOO_LONG:请求URI太长了 HTTP/1.1 RFC 7231, 6.5.12 节
415 UNSUPPORTED_MEDIA_TYPE:不支持的媒体格式 HTTP/1.1 RFC 7231, 6.5.13 节
416 REQUESTED_RANGE_NOT_SATISFIABLE HTTP/1.1 Range Requests RFC 7233, 4.4 节
417 EXPECTATION_FAILED:期望失败 HTTP/1.1 RFC 7231, 6.5.14 节
421 MISDIRECTED_REQUEST HTTP/2 RFC 7540, 9.1.2 节
422 UNPROCESSABLE_ENTITY:可加工实体 WebDAV RFC 4918, 11.2 节
423 LOCKED:锁着 WebDAV RFC 4918, 11.3 节
424 FAILED_DEPENDENCY:失败的依赖 WebDAV RFC 4918, 11.4 节
426 UPGRADE_REQUIRED:升级需要 HTTP/1.1 RFC 7231, 6.5.15 节
428 PRECONDITION_REQUIRED:先决条件要求 Additional HTTP Status Codes RFC 6585
429 TOO_MANY_REQUESTS:太多的请求 Additional HTTP Status Codes RFC 6585
431 REQUEST_HEADER_FIELDS_TOO_LARGE:请求头太大 Additional HTTP Status Codes RFC 6585
451 UNAVAILABLE_FOR_LEGAL_REASONS HTTP 状态码用于报告法律障碍 RFC 7725
500 INTERNAL_SERVER_ERROR:内部服务错误 HTTP/1.1 RFC 7231, 6.6.1 节
501 NOT_IMPLEMENTED:不可执行 HTTP/1.1 RFC 7231, 6.6.2 节
502 BAD_GATEWAY:无效网关 HTTP/1.1 RFC 7231, 6.6.3 节
503 SERVICE_UNAVAILABLE:服务不可用 HTTP/1.1 RFC 7231, 6.6.4 节
504 GATEWAY_TIMEOUT:网关超时 HTTP/1.1 RFC 7231, 6.6.5 节
505 HTTP_VERSION_NOT_SUPPORTED:HTTP版本不支持 HTTP/1.1 RFC 7231, 6.6.6 节
506 VARIANT_ALSO_NEGOTIATES:服务器存在内部配置错误 透明内容协商在: HTTP RFC 2295, 8.1 节(实验性)
507 INSUFFICIENT_STORAGE:存储不足 WebDAV RFC 4918, 11.5 节
508 LOOP_DETECTED:循环检测 WebDAV Binding Extensions RFC 5842, 7.2 节(实验性)
510 NOT_EXTENDED:不扩展 WebDAV Binding Extensions RFC 5842, 7.2 节(实验性)
511 NETWORK_AUTHENTICATION_REQUIRED:要求网络身份验证 Additional HTTP Status Codes RFC 6585, 6 节

为了保持向后兼容性,枚举值也以常量形式出现在 http.client 模块中,。 枚举名等于常量名 (例如 http.HTTPStatus.OK 也可以是 http.client.OK)。

http.client 对象

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

参见 The Requests 是一个高级的实现http协议的http客户端接口库.

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

强烈建议看源代码 Lib/http/client.py

我摘取其中关于http请求状态的描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

(null)
|
| HTTPConnection()
v
Idle
|
| putrequest()
v
Request-started
|
| ( putheader() )* endheaders()
v
Request-sent
|\_____________________________
| | getresponse() raises
| response = getresponse() | ConnectionError
v v
Unread-response Idle
[Response-headers-read]
|\____________________
| |
| response.read() | putrequest()
v v
Idle Req-started-unread-response
______/|
/ |
response.read() | | ( putheader() )* endheaders()
v v
Request-started Req-sent-unread-response
|
| response.read()
v
Request-sent

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

HTTPConnection 的实例代表与 HTTP 的一个连接事务。 它的实例化应当传入一个主机和可选的端口号。 如果没有传入端口号,如果主机字符串的形式为 主机:端口 则会从中提取端口,否则将使用默认的 HTTP 端口(80)。 如果给出了可选的 timeout 参数,则阻塞操作(例如连接尝试)将在指定的秒数之后超时(如果未给出,则使用全局默认超时设置)。 可选的 source_address 参数可以为一个 (主机, 端口) 元组,用作进行 HTTP 连接的源地址。 可选的 blocksize 参数可以字节为单位设置缓冲区的大小,用来发送文件类消息体。

举个例子,以下调用都是创建连接到同一主机和端口的服务器的实例:

1
2
3
4
>>> 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)
  • `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 各选项的 ssl.SSLContext 实例。

  • class http.client.`HTTPResponse`(sock, debuglevel=0, method=None, url=None)

在成功连接后返回类的实例,而不是由用户直接实例化。

异常

  • 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() 引发,表明远端已关闭连接。

常量

  • 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.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,但存在请求正文,那么这些头字段中的一个会自动设定。如果 bodyNone,那么对于要求正文的方法 (PUTPOST,和 PATCH),Content-Length 头会被设为 0。如果 body 是字符串或者类似字节的对象,并且也不是 文件,Content-Length 头会设为正文的长度。任何其他类型的 body (一般是文件或迭代器)会按块编码,这时会自动设定 Transfer-Encoding 头以代替 Content-Length。

headers 中指定 Transfer-Encoding 时, encode_chunked 是唯一相关的参数。如果 encode_chunkedFalse,HTTPConnection 对象会假定所有的编码都由调用代码处理。如果为 True,正文会按块编码。

  • 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() 方法:

    1
    2
    3
    4
    >>> import http.client
    >>> conn = http.client.HTTPSConnection("localhost", 8080)
    >>> conn.set_tunnel("www.python.org")
    >>> conn.request("HEAD","/index.html")
  • HTTPConnection.connect()

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

  • HTTPConnection.close()

    关闭到服务器的连接。

  • HTTPConnection.blocksize

    用于发送文件类消息体的缓冲区大小。

  • HTTPConnection.send(data)

    发送数据到服务器 。这个方法直接使用将会在endheaders()方法后和 getresponse() 方法调用之前被调用

HTTPResponse 对象

HTTPResponse 对象实例绑定从服务器返回的 Http response 内容。 response是一个可迭代对象,可以使用with上下文语句来管理。

方法

  • HTTPResponse.read([amt])

    读取并返回response body

  • HTTPResponse.`readinto`(b)

    读取从 response body 的b长度的字节放到 buffer b中,并返回这个字节b。

  • HTTPResponse.getheader(name, default=None)

    如果有匹配的header name,则返回 header name的值。如果不止一个header name的名字,则返回所有的值的字符串,通过逗号连接。

  • HTTPResponse.getheaders()

    返回一个包含header和value的元组元素的列表

  • HTTPResponse.fileno()

    Return the fileno of the underlying socket.

    返回底层套接字的fileno

  • HTTPResponse.msg

    一个http.client.HTTPMessage 消息的实例,包含response header。 http.client.HTTPMessageemail.message.Message的子类

  • HTTPResponse.version

    Http response版本号,例如 HTTP/1.0, 11 for HTTP/1.1.

  • HTTPResponse.`status`

    由服务器返回的状态码。

  • HTTPResponse.reason

    从服务器返回的状态码

  • HTTPResponse.debuglevel

    一个 debugging hook. 如果 debuglevel 大于0, 消息将会被打印到控制台。

  • HTTPResponse.closed

    如果stream关闭,返回true

实例:

一个使用get请求的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> 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方法的实例

1
2
3
4
5
6
7
8
9
10
11
>>> 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提交请求的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> 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请求的实例

1
2
3
4
5
6
7
8
9
10
11
>>> # 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 对象

一个 http.client.HTTPMessage的实例包含了http response 请求头. 是 email.message.Message类的具体实现.

总结

通过阅读源码加深了对http协议的理解,看python实现的方式受益良多。继续加油!

坚持原创技术分享,您的支持将鼓励我继续创作!