跳转到主要内容

为ASGI应用程序和框架提供即插即用的MessagePack支持

项目描述

msgpack-asgi

Build Status Coverage Package version

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-Typeapplication/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响应类。

项目详情


下载文件

下载适合您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

msgpack-asgi-1.1.0.tar.gz (8.4 kB 查看哈希值)

上传时间

构建分布

msgpack_asgi-1.1.0-py3-none-any.whl (7.1 kB 查看哈希值)

上传于 Python 3

由以下支持