为ASGI应用程序和框架提供即插即用的MessagePack支持
项目描述
msgpack-asgi
msgpack-asgi
允许您通过一行代码将自动 MessagePack 内容协商添加到 ASGI 应用程序(Starlette、FastAPI、Quart 等)
app.add_middleware(MessagePackMiddleware)
(您可能需要将此代码片段适配到您框架特定的中间件 API。)
这为您提供了MessagePack的带宽使用降低优势,而无需更改现有代码。
注意:这会带来CPU使用成本的代价,因为 MessagePackMiddleware
将在您的应用程序继续解码和编码 JSON 数据的同时执行 MsgPack 解码(另见 如何工作)。如果您的用例对CPU敏感,而不仅仅是严格关注减少网络带宽,那么这个包可能不适合您。
安装
使用pip安装
pip install "msgpack-asgi==1.*"
快速入门
首先,您需要一个ASGI应用程序。让我们使用这个示例应用程序,它公开了一个返回JSON数据的端点
# For convenience, we use some ASGI components from Starlette.
# Install with: `$ pip install starlette`.
from starlette.requests import Request
from starlette.responses import JSONResponse
async def get_response(request):
if request.method == "POST":
data = await request.json()
return JSONResponse({"data": data}, status_code=201)
else:
return JSONResponse({"message": "Hello, msgpack!"})
async def app(scope, receive, send):
assert scope["type"] == "http"
request = Request(scope=scope, receive=receive)
response = await get_response(request)
await response(scope, receive, send)
然后,将您的应用程序包裹在 MessagePackMiddleware
中
from msgpack_asgi import MessagePackMiddleware
app = MessagePackMiddleware(app)
使用ASGI服务器提供您的应用程序,例如使用 Uvicorn
uvicorn app:app
现在,让我们发送一个接受MessagePack数据的请求
curl -i http://localhost:8000 -H "Accept: application/x-msgpack"
您应该得到以下输出
HTTP/1.1 200 OK
date: Fri, 01 Nov 2019 17:40:14 GMT
server: uvicorn
content-length: 25
content-type: application/x-msgpack
��message�Hello, msgpack!
发生了什么?因为我们告诉应用程序我们接受MessagePack编码的响应,所以 msgpack-asgi
自动将 Starlette 应用程序返回的JSON数据转换为MessagePack。
我们可以通过在Python中再次发出请求并解码响应内容来确保响应包含有效的MessagePack数据。
>>> import requests
>>> import msgpack
>>> url = "http://localhost:8000"
>>> headers = {"accept": "application/x-msgpack"}
>>> r = requests.get(url, headers=headers)
>>> r.content
b'\x81\xa7message\xafHello, msgpack!'
>>> msgpack.unpackb(r.content, raw=False)
{'message': 'Hello, msgpack!'}
msgpack-asgi
也支持反向操作:它会自动将客户端发送的MessagePack编码数据解码为JSON。我们可以通过向我们的示例应用程序发送带有MessagePack编码体的POST
请求来尝试这一功能。
>>> import requests
>>> import msgpack
>>> url = "http://localhost:8000"
>>> data = msgpack.packb({"message": "Hi, there!"})
>>> headers = {"content-type": "application/x-msgpack"}
>>> r = requests.post(url, data=data, headers=headers)
>>> r.json()
{'data': {'message': 'Hi, there!'}}
这就是全部内容!你现在可以减少负载的大小了。
高级用法
自定义实现
msgpack-asgi
支持自定义默认的编码/解码实现。这对于通过替代的msgpack实现来调整应用性能非常有用,无论是用于编码、解码还是两者都使用。
为此,请使用以下参数
packb
- (可选,类型:(obj: Any) -> bytes
,默认:msgpack.packb
) - 用于编码传出数据。unpackb
- (可选,类型:(data: bytes) -> Any
,默认:msgpack.unpackb
) - 用于解码传入数据。
例如,要使用ormsgpack
库进行编码
import ormsgpack # Installed separately.
from msgpack_asgi import MessagePackMiddleware
def packb(obj):
option = ... # See `ormsgpack` options.
return ormsgpack.packb(obj, option=option)
app = MessagePackMiddleware(..., packb=packb)
限制
msgpack-asgi
不支持请求或响应流。这是因为必须在内存中加载完整的请求和响应体内容后才能重新编码。
它的工作原理
围绕MessagePackMiddleware
包装的ASGI应用程序将根据客户端的能力执行自动内容协商。更精确地说
- 如果客户端使用
application/x-msgpack
内容类型发送MessagePack编码数据,msgpack-asgi
将自动将主体重新编码为JSON,并将请求的Content-Type
重写为application/json
以供您的应用程序消费。(注意:这意味着应用程序将无法区分MessagePack和JSON客户端请求。) - 如果客户端发送了
Accept: application/x-msgpack
头,msgpack-asgi
将自动将任何JSON响应数据重新编码为MessagePack,供客户端消费。
(在其他情况下,msgpack-asgi
不会进行任何干预。)
许可
MIT
变更日志
本项目所有显著变更都将记录在此文件中。
格式基于Keep a Changelog。
1.1.0 - 2021-10-26
新增
- 通过
packb=...
和unpackb=...
可选参数支持自定义编码/解码实现,允许使用替代的msgpack库。(拉取请求#20)
修复
- 正确重写请求的
Content-Type
为application/json
。(拉取请求#24)
1.0.0 - 2020-03-26
第一个生产/稳定版本。
变更
- 切换到私有模块命名。组件现在应从根包导入,例如
from msgpack_asgi import MessagePackMiddleware
。(拉取请求#5)
修复
- 添加缺少的
MANIFEST.in
。(拉取请求#4)
0.1.0 - 2019-11-04
初始发布。
新增
- 添加
MessagePackMiddleware
ASGI中间件。 - 添加
MessagePackResponse
ASGI响应类。
项目详情
下载文件
下载适合您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。