详解Python中httptools模块的使用

详解Python中httptools模块的使用_第1张图片

httptools 是一个 HTTP 解析器,它首先提供了一个 parse_url 函数,用来解析 URL。这篇文章就来和大家聊聊它的用法吧,感兴趣的可以了解一下

如果你用过 FastAPI 的话,那么你一定知道 uvicorn,它是一个基于 uvloop 和 httptools 实现的高性能 ASGI 服务器。

其中 uvloop 采用 Cython 编写,用于替换 asyncio 中的事件循环,可以让 asyncio 速度增加 2 到 4 倍。而 httptools 是基于 C 语言实现的 HTTP 解析器,用来解析 HTTP 请求的。

本次就来聊一聊 httptools 这个模块的详细用法,至于 uvloop、uvicorn 等相关内容,后续我会一点一点补充上去,并从源码的角度全给说明白(挖了个坑)。

httptools 是一个 HTTP 解析器,它首先提供了一个 parse_url 函数,用来解析 URL。

import httptools

# 第一个参数必须是 bytes 对象
url = httptools.parse\_url(
    b"http://www.baidu.com"
)
# 返回一个 URL 对象
print(url.\_\_class\_\_)
"""

"""

那么这个 URL 对象有哪些属性呢?

详解Python中httptools模块的使用_第2张图片

通过源码可知,总共有七个属性,我们来测试一下。

import httptools

# 第一个参数是 bytes 对象
url = b"http://satori:[email protected]:80/s?wd=koishi#flag"
url\_obj = httptools.parse\_url(url)

print("协议:", url\_obj.schema)
print("IP:", url\_obj.host)
print("端口:", url\_obj.port)
print("路径:", url\_obj.path)
print("查询参数:", url\_obj.query)
print("锚点:", url\_obj.fragment)
print("用户信息:", url\_obj.userinfo)
"""
协议: b'http'
IP: b'www.baidu.com'
端口: 80
路径: b'/s'
查询参数: b'wd=koishi'
锚点: b'flag'
用户信息: b'satori:123456'
"""

比较简单,如果参数不符合 URL 的标准格式,那么会抛出 HttpParserInvalidURLError 错误。

然后是 HTTP 请求报文和响应报文的解析,因为报文只是一坨字节流,需要将它解析成某个 Request 对象或 Response 对象,而 httptools 就是干这件事情的。

首先来看一下报文格式,请求报文如下:

详解Python中httptools模块的使用_第3张图片

接下来是响应报文:

详解Python中httptools模块的使用_第4张图片

所以无论是请求报文还是响应报文,都由 起始行 + 请求头/响应头 + 请求体/响应体 组成。而我们在拿到原始的报文之后,也可以很方便地进行解析,从图中可以看出最后一个 Header 字段和响应体之间有两个换行,而换行用 \r\n 表示。因此我们只要按照 “\r\n\r\n” 进行 split 即可,会得到一个数组,数组的第二个元素就是请求体/响应体,第一个元素就是起始行 + 请求头/响应头。

然后对数组的第一个元素按照 “\r\n” 再进行 split,又可以得到一个数组,该数组的第一个元素就是起始行,剩余的元素就是请求头/响应头。

所以我们在拿到报文之后,完全可以自己手动解析,但 httptools 是用 C 实现的,所以速度会快一些,但干的事情是一样的。下面来看看 httptools 如何解析请求报文:

from pprint import pprint
import httptools

# 请求报文
request\_payload = b"""POST /index?a=1 HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 26
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Accept: text/html
Accept-Encoding: gzip, deflate, sdch
Cookie: \_octo=GH1.1.1989111283.1493917476; logged\_in=yes

{"name":"satori","age":17}"""

class Request:
    """
    将请求报文的解析结果封装成 Request 对象
    """
    def \_\_init\_\_(self):
        self.headers = {}
        self.body = b""
        self.path = None

    def on\_url(self, path: bytes):
        self.path = path

    def on\_header(self, name: bytes, value: bytes):
        self.headers\[name\] = value

    def on\_body(self, body: bytes):
        self.body = body

# 实例化 Request 对象
request = Request()
# 将 request 作为参数传到 HttpRequestParser 中
parser = httptools.HttpRequestParser(request)
# 传入请求报文,进行解析
parser.feed\_data(request\_payload)

# 获取 HTTP 版本
print(parser.get\_http\_version())
"""
1.1
"""
# 是否是长链接(Connection 指定为 keep-alive)
print(parser.should\_keep\_alive())
"""
True
"""
# 获取请求方法
print(parser.get\_method())
"""
b'POST'
"""
# 以上几个都是 HttpRequestParser 对象的方法

# 获取路径
print(request.path)
"""
b'/index?a=1'
"""

# 获取请求头
pprint(request.headers)
"""
{b'Accept': b'text/html',
 b'Accept-Encoding': b'gzip, deflate, sdch',
 b'Cache-Control': b'max-age=0',
 b'Connection': b'keep-alive',
 b'Content-Length': b'26',
 b'Cookie': b'\_octo=GH1.1.1989111283.1493917476; logged\_in=yes',
 b'Host': b'localhost:8080',
 b'Upgrade-Insecure-Requests': b'1'}
"""
# Cookie 也是请求头的一部分,但在解析的时候会单独拿出来
# 再解析成一个字典,然后通过 request.cookies 获取

# 获取请求体
print(request.body)
"""
b'{"name":"satori","age":17}'
"""

以上就是请求报文的解析,再来看看响应报文。

from pprint import pprint
import httptools

# 响应报文
response\_payload = b"""HTTP/1.1 200 OK
Server: TornadoServer/6.1
Content-Type: text/html; charset=UTF-8
Date: Sun, 22 May 2022 17:54:11 GMT
Content-Length: 21

name: satori, age: 17"""

class Response:
    """
    将响应报文的解析结果封装成 Response 对象
    """
    def \_\_init\_\_(self):
        self.headers = {}
        self.body = b""
        self.status = b""

    def on\_header(self, name: bytes, value: bytes):
        self.headers\[name\] = value

    def on\_body(self, body: bytes):
        self.body = body

    def on\_status(self, status: bytes):
        self.status = status

# 实例化 Response 对象
response = Response()
# 将 response 作为参数传到 HttpResponseParser 中
parser = httptools.HttpResponseParser(response)
# 传入响应报文,进行解析
parser.feed\_data(response\_payload)

# 获取 HTTP 版本
print(parser.get\_http\_version())
"""
1.1
"""
# 是否是长链接(不指定 Connection,默认为长连接)
print(parser.should\_keep\_alive())
"""
True
"""
# 获取状态码
print(parser.get\_status\_code())
"""
b'OK'
"""

# 获取状态码对应的描述
print(response.status)
"""
b'OK'
"""

# 获取响应头
pprint(response.headers)
"""
{b'Content-Length': b'21',
 b'Content-Type': b'text/html; charset=UTF-8',
 b'Date': b'Sun, 22 May 2022 17:54:11 GMT',
 b'Server': b'TornadoServer/6.1'}
"""

# 获取响应体
print(response.body)
"""
b'name: satori, age: 17'
"""

以上就是请求报文和响应报文的解析,但如果你不是手动发送 TCP 请求的话,那么该模块基本用不到。因为对于任何一个成熟的模块而言,都具备了报文解析功能。像 requests, httpx, aiohttp 等等,以及一些 web 框架,它们在拿到报文之后会自动解析成某个对象,我们直接通过指定的属性获取即可。

而 httptools 便是 uvicorn 的报文解析器,我们在使用 uvicorn 的时候,uvicorn 内部也会自动通过 httptools 将报文解析好,而不需要我们手动解析。

因此这里介绍的 httptools 了解一下即可,我们只需要知道它是基于 C 实现的,性能非常高就行。但我们不会手动使用它,而是在使用某个框架(uvicorn)的时候,由框架自动帮我们将报文解析好。


关于Python技术储备

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

保存图片微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

详解Python中httptools模块的使用_第5张图片
一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
在这里插入图片描述

二、Python基础学习视频

② 路线对应学习视频

还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~在这里插入图片描述
在这里插入图片描述

③练习题

每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈!
在这里插入图片描述
因篇幅有限,仅展示部分资料

三、精品Python学习书籍

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
在这里插入图片描述

四、Python工具包+项目源码合集
①Python工具包

学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦!
在这里插入图片描述

②Python实战案例

光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿!
在这里插入图片描述

③Python小游戏源码

如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味!
在这里插入图片描述

五、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
在这里插入图片描述
在这里插入图片描述

六、Python兼职渠道

而且学会Python以后,还可以在各大兼职平台接单赚钱,各种兼职渠道+兼职注意事项+如何和客户沟通,我都整理成文档了。
在这里插入图片描述

这份完整版的Python全套学习资料已经上传CSDN,朋友们如果需要可以保存图片微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

详解Python中httptools模块的使用_第6张图片

你可能感兴趣的:(python,开发语言,计算机网络,经验分享,学习,深度学习,http)