详解Python中httptools模块的使用

在这里插入图片描述

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\_\_)
"""
<class 'httptools.parser.parser.URL'>
"""

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

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

import httptools

# 第一个参数是 bytes 对象
url = b"http://satori:123456@www.baidu.com: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 就是干这件事情的。

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

接下来是响应报文:

所以无论是请求报文还是响应报文,都由 起始行 + 请求头/响应头 + 请求体/响应体 组成。而我们在拿到原始的报文之后,也可以很方便地进行解析,从图中可以看出最后一个 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所有方向的学习路线

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

二、Python基础学习视频

② 路线对应学习视频

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

③练习题

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

三、精品Python学习书籍

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

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

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

②Python实战案例

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

③Python小游戏源码

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

五、面试资料

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

六、Python兼职渠道

而且学会Python以后,还可以在各大兼职平台接单赚钱,各种兼职渠道+兼职注意事项+如何和客户沟通,我都整理成文档了。
在这里插入图片描述
在这里插入图片描述
这份完整版的Python全套学习资料已经上传CSDN,朋友们如果需要可以保存图片微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/201415.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

京东API商品详情接口,通过商品ID获取商品名称,淘宝主图,价格,颜色规格尺寸,库存,SKU数据等调用示例

要接入京东API接口以采集电商平台上的商品数据&#xff0c;可以按照以下步骤进行&#xff1a; 注册并获取API密钥&#xff1a;在使用API接口之前&#xff0c;需要注册并获取API密钥。API密钥是识别身份的唯一标识符。每个API接口都有自己的注册、认证和授权过程&#xff0c;因…

Find My电容笔|苹果Find My技术与电容笔结合,智能防丢,全球定位

随着平板电脑的流行&#xff0c;有不少厂商都投入到了电容笔的开发当中&#xff0c;现在的电容笔不仅在精度上有了提高&#xff0c;甚至在笔触和压感上的研究都有进步。电容笔是利用导体材料制作的具有导电特性、用来触控电容式屏幕完成人机对话操作用的笔&#xff0c;电容笔通…

tsx语法

安装JSX库 安装完之后在vite.config.ts进行插件使用&#xff0c;代码如下&#xff1a; 然后就可以愉快的使用TSX来开发Vue组件了&#xff0c;下面主要说一下SFC和TSX的部分区别。 基本语法对照 defineComponent 和 setup setup中函数的返回值有多种方式&#xff0c;可以直接…

异常数据检测 | Python实现oneclassSVM模型异常数据检测

支持向量机(SVM)的异常检测 SVM通常应用于监督式学习,但OneClassSVM[8]算法可用于将异常检测这样的无监督式学习,它学习一个用于异常检测的决策函数其主要功能将新数据分类为与训练集相似的正常值或不相似的异常值。 OneClassSVM OneClassSVM的思想来源于这篇论文[9],SVM使用…

挑战传统IT:RPA以更低的成本和更高的效率领跑数字化转型

在企业数字化进程中&#xff0c;传统的IT解决方案往往带来高成本和低效率的问题。因此&#xff0c;如何顺利地、平稳地进行数字化转型对企业来说是核心考虑。 为此&#xff0c;本文将深入探讨RPA&#xff08;Robotic Process Automation&#xff09;如何以其独特的优势&#xf…

RabbitMQ消息模型之发布订阅Publish-Subscribe

发布订阅模型 Publish/Subscribe 发布订阅模型也称为广播模型&#xff0c;交换机类型需要指定为Fanout&#xff0c;正如从名称中猜到的那样&#xff0c;它是将接收到的所有消息广播到它知道的所有队列中。每个消费者都监听自己的队列&#xff0c;所以同一个消息&#xff0c;会…

MNIST手写数字识别

本篇文章是博主在人工智能等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在Pytorch&#xff…

OpenMMlab导出FCN模型并用onnxruntime推理

导出onnx文件 直接使用脚本 import torch from mmseg.apis init_modelconfig_file configs/fcn/fcn_r18-d8_4xb2-80k_cityscapes-512x1024.py checkpoint_file fcn_r18-d8_512x1024_80k_cityscapes_20201225_021327-6c50f8b4.pth model init_model(config_file, checkpoin…

YOLOv8 代码部署

一、获取代码 YOLOv8官方GitHub网址 https://github.com/ultralytics/ultralytics 获取YOLOv8代码压缩包 二、虚拟环境配置 这个就不写了&#xff0c;装个Anaconda&#xff0c;网上教程很多 三、PyCharm安装与配置&#xff08;可选&#xff09; 这个也不写了&#xff0c;…

磁环电感参数计算

磁环电感参数计算 1.什么是电感磁饱和2.电感饱和的原因3.电感饱和带来的影响3.1 感应电动势变化3.2 电感值变化3.3 功率损耗增加3.4 系统稳定性受到影响4.饱和电流计算最近在做DC/DC电源,电感是用磁环绕制的,所以关注一下磁环绕制电感参数的计算,学习学习。 某款磁环参数。 …

SpringBoot——Swagger2 接口规范

优质博文&#xff1a;IT-BLOG-CN 如今&#xff0c;REST和微服务已经有了很大的发展势头。但是&#xff0c;REST规范中并没有提供一种规范来编写我们的对外REST接口API文档。每个人都在用自己的方式记录api文档&#xff0c;因此没有一种标准规范能够让我们很容易的理解和使用该…

3dMax导出glft和glb格式模型插件Max2Babylon教程

为了满足Autodesk提供自己的导出管道之前的迫切需要&#xff0c;Babylon.js导出器可用于3dMax。导出器可以将3dMax场景导出为.glTF文件、.glb文件或.babylon文件。 【适用版本】 3dMax2015 - 2024 【安装方法】 1.选择和自己电脑中3dMax所对应的插件版本&#xff0c;解压缩。…

基于Qt MP3音频播放器示例(可制作音频播放器)

​本次MP3文件也给出来,方便大家调试。话不多说直接上源码。 整个项目下载地址:CSDN:GetCode 昵称-》Qt魔术师:https://gitcode.com/m0_45463480/QtMP3/tree/main## .pro # 指定项目类型为应用程序。TEMPLATE = app# 指定项目的名称为musicplayerTARGET = musicplayer# 添…

Matlab下载许可证文件 教程(在账号有许可证的前提下)

文章目录 Part.I IntroductionPart.II 许可证文件过期解决方案Chap.I 使用 Internet 自动激活Chap.II 在不使用 Internet 的情况下手动激活 Part.I Introduction 本文主要介绍&#xff0c;在 Mathwork 账号有许可证的前提下&#xff0c;下载许可证的操作流程。 好久没有用 Mat…

使用Redis实现接口防抖

说明&#xff1a;实际开发中&#xff0c;我们在前端页面上点击了一个按钮&#xff0c;访问了一个接口&#xff0c;这时因为网络波动或者其他原因&#xff0c;页面上没有反应&#xff0c;用户可能会在短时间内再次点击一次或者用户以为没有点到&#xff0c;很快的又点了一次。导…

基于springboot的电影院管理系统的设计与实现 (含论文和源码视频导入教程)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于springboot的电影院管理系统7拥有两种角色 管理员&#xff1a;用户管理、购票统计、电影管理、电影类型管理、放映厅管理、订单管理等 用户&#xff1a;登录注册、查看各种信息、购票…

uniapp打包ios有时间 uniapp打包次数

我们经常用的解决方案有,分包,将图片上传到服务器上,减少插件引入。但是还有一个方案好多刚入门uniapp的人都给忽略了,就是在源码视图中配置,开启分包优化。 1.分包 目前微信小程序可以分8个包,每个包的最大存储是2M,也就是说你文件总体的大小不能超过16M,每个包的大…

【模板】KMP算法笔记

练习链接&#xff1a;【模板】KMP - 洛谷 题目&#xff1a; 输入 ABABABC ABA 输出 1 3 0 0 1 思路&#xff1a; 根据题意&#xff0c;用到的是KMP算法&#xff0c;KMP算法思想是通过一个一个匹配首字母的原理进行整个匹配效果&#xff0c;当某个首字母不匹配的时候&#x…

箭头函数与普通函数:谁更胜一筹?

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

ASUS(华硕) B760M-AYW WIFI D4_解决wifi不能使用

1、最近新购买了一套 diy电脑主机&#xff0c;选用的是 ASUS B760M-AYW WIFI D4电脑主板 win10 系统&#xff0c;到货后 发现右下角电脑图标处及网络适配器中 没有wifi选项 首先 在官网和旗舰店客服处&#xff0c;确认了 该主板 有集成wifi模块&#xff0c;鲨鱼鳍天线未安装…