3

我正在尝试实现一个自定义主体类型,该类型将包含一个解析的 JSON 树对象。这项任务看起来很自然,但我找不到使用 Beast 生成携带 JSON 的非分块 HTTP 消息的方法。我有一个通过包装 libmicrohttpd 和 libcurl 实现的 REST 客户端/服务器,但我更愿意改用 Boost Beast。

据我了解,问题在于主体类型的size(value_type const&)方法接收到对要序列化的主体值的引用(在我的情况下是 JSON 树对象),但是没有实际的方法来确定字符串化 JSON 的确切长度把它串起来。但是,如果我删除该size()方法,Beast 会认为我要求的是分块传输编码。当然,分块编码本身并没有什么问题,但对我来说,这可能意味着修复一些自动化和监控脚本,更不用说集成测试了。

我想做的是为我正在准备的消息分配一个 JSON 对象,然后 Beast 询问作者,而不是询问body::size()有效负载的大小。这对我来说似乎是合乎逻辑的,因为实际的 HTTP 消息正文(序列化 JSON)与内存中的活动 JSON 对象完全不同,它是body::writer生成用于传输的正文字节。我错了吗?

无论如何,你认为有一个很好的方法来解决这个问题吗?

提前感谢您的时间和精力!

问候, 弗拉德

4

1 回答 1

1

谢谢你的好话,我很高兴看到车身定制系统得到一些关注!您在问题中写的大部分内容都是正确的。如果您希望 Beast 在您调用时设置 Content-Length 字段,message::prepare_payload那么您必须在Body::size. BodyWriter直到序列化时刻才会创建这个问题最自然的解决方案是避免提供Body::size并让 Beast 在序列化您的身体类型时使用分块传输编码。我还应该注意,当您序列化 JSON 时,最好在编写器中一次执行一点,而不是将整个内容转换为字符串。这就是拥有 writer 对象的目的,以保持中间状态并允许增量序列化。否则,您必须为整个序列化表示分配内存,这样效率较低。

更新:

body::size()并且message::prepare_payload不打算以您想要的方式使用。如果我理解你想要做什么,那么这个函数应该处理它:

/** Prepare a message with a JSON payload.

    This function accepts ownership of a message with a JSON body
    and converts the JSON to string, returning a new message with
    a string body. The Content-Length field is set on the new
    message. All other fields are transferred over unmodified.
*/
template<
    bool isRequest,
    class Allocator>
message<
    isRequest,
    string_body,
    basic_fields<Allocator>>
prepare(
    message<
        isRequest,
        json_body,
        basic_fields<Allocator>>&& m)
{
    message<
        isRequest,
        string_body,
        basic_fields<Allocator>> result{
            std::move(m.base()),
            json_to_string(m.body())};
    result.prepare_payload();
    return result;
}
于 2018-01-11T14:43:11.590 回答