httpbin源码解析
文章目录
httpbin是requests作者Kenneth Reitz的项目,是一个使用flask制作的http协议演示项目。学习这个项目,我们大概可以获得两个小收获:
- 学习如何使用flask制作一个网站
- 学习一些http协议的细节
正式开始之前,对flask不熟悉的朋友,欢迎去回顾flask的源码解析:
- flask 源码阅读-上
- flask 源码阅读-中
- flask 源码阅读-下
httpbin的项目结构
我们选用httpbin的v0.7.0版本,项目大概结构如下:
模块 | 功能 |
---|---|
templates | 模版文件 |
core | 功能实现 |
fileters | 一些装饰器实现 |
helpers | 一些帮助类 |
structures | 数据结构实现 |
utils | 一些工具类 |
Dockerfile | docker镜像文件 |
test_httpbin.py | 单元测试用例 |
httpbin的使用
httpbin项目,可以直接在https://httpbin.org/网站感受,网站交互式的展示了一些http的使用, 比如get
请求
- 使用http协议的GET方法请求数据
- request的header中设置 accept:application/json 接收json输出
- 展示response的状态码,header和body
我们也可以在终端中使用curl观测:
|
|
-v 参数跟踪请求过程
对比可发现这和网站上展示的数据是一致的。httpbin网站上还有很多http方法的演示,大家可以自己逐一尝试。
httpbin的实现
httpbin的部署
Dockerfile文件描述了httpbin如何使用gunicorn部署运行的:
|
|
gunicorn启动httpbin:app,这个app在httpbin包下,由core模块提供:
|
|
- 启动app的同时,设置flask项目的模版文件路径在templates目录,这个目录是和core文件同级。
get API的实现
/get
API返回请求的url,args,header和origin,并将结果json化输出:
|
|
jsonify输出使用了flask提供的jsonify功能,仅仅在默认结果上增加一个换行输出:
|
|
get_dict是对request的操作,flask的request会绑定到线程上,所以不需要传递request参数到get_dict函数:
|
|
可以使用下面的命令行演示args参数, name=shawn&age=18的查询,会自动转换成args字典:
|
|
http是超文本协议,所以age参数默认是字符串,而不是数字
http-bin还提供了两个基于flask的Middlewares实现,其中一个是after_request,在请求完成后处理跨域问题,给响应header增加两个跨域标志:
|
|
在chrome浏览的console中可以这样验证:
|
|
seo
在web2.0时代,seo的支持很重要,可以免费利用搜索引擎带来很多访问量。robots.txt是网站和搜索引擎爬虫的约定,httpbin中提供了一个简单的实现:
|
|
- robots.txt使用纯文本方式输出
robots.txt的内容是禁止/deny
目录的访问:
|
|
如果不遵守robots.txt访问了/deny
目录,http-bin的示意是会生气,大家可以自己去测试感受一下。
Kenneth Reitz 这里设计的挺有意思的,包括代码里面402的FWord,展示作者活泼的一面
压缩
http的压缩,支持gzip,deflate和brotli三种算法。下面是gzip支持实现:
|
|
gzip使用装饰器实现:
|
|
- 使用gzip压缩数据
- 压缩完成的数据要修改2个响应的http头Content-Encoding和Content-Length
比较特别的是这里的gzip装饰器使用了decorator这个库实现。和普通的装饰器不一样,decorator号称给人类使用的装饰器,核心特点就是没有多层嵌套的函数结构,函数的第一个参数就是函数,然后args和kwargs是原生函数的动态参数。
Basic-Auth认证
http-bin还提供了简单认证的实现。简单认证情况下,浏览器默认会提供一个用户名和密码的输入框,验证通过后才可以继续访问:
下面是其代码:
|
|
使用curl更容易跟踪到这个过程:
|
|
可以看到第一次会收到401,这时候响应头上有WWW-Authenticate:
|
|
然后 浏览器 会自动弹出用户名和密码输入框,用户输入用户名和密码后通过认证。这个窗口不需要应用程序进行开发。
流
stream流传输,可以用于http文件的下载,比如下面的实现:
|
|
测试中我们可以看到一次请求,响应分成了多段接收,这样对于大的文件,可以进行断点续传。
|
|
httpbin里还提供了一些其它的http示例,大家可以自行体验,本文就不再一一介绍了。
单元测试
/get
API的单元测试展示了如何使用unittest测试一个http接口:
|
|
- 在setUp方法中httpbin.app.test_client()返回一个测试app,模拟服务
- self.app.get(’/get’, headers={‘User-Agent’: ’test’}) 模拟requests请求
- response方法就和真实的http响应一致
这种单元测试方法,脱离了http服务,执行更高效。在django框架中也有类似的方式。
小结
本文我们学习了基于flask框架实现的网站httpbin源码,了解了一些http协议实现细节,相信对大家掌握http协议也有一定的帮助。
小技巧
在utils中提供了一个很巧妙的带权重的随机算法:
|
|
参考链接
文章作者 shawn
上次更新 2022-01-09