Boost Beast:当内容长度不易获得时,如何使用自定义正文生成非分块响应?

时间:2018-01-08 13:00:16

标签: c++ json boost boost-beast

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

正如我所理解的那样,问题是正文类型的size(value_type const&)方法接收对要序列化的正文值的引用(在我的情况下是一个JSON树对象),但是没有确定字符串化JSON的确切长度的方法,而不实际字符串化。但是,如果我删除size()方法,Beast认为我要求分块传输编码。当然,分块编码本身没有任何问题,但对我来说,这可能意味着修复一些自动化和监控脚本,更不用说集成测试了。

我想要做的是将JSON对象分配给我正在准备的消息,然后将Beast分配给 writer ,而不是body::size()来查看有效负载大小。这对我来说似乎是合乎逻辑的,因为实际的HTTP消息体(序列化的JSON)与内存中的实时JSON对象完全不同,并且 body :: writer 生成用于传输的正文字节。我错了吗?

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

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

此致 维拉德

1 个答案:

答案 0 :(得分:0)

感谢您的客气话,我很高兴看到Body定制系统得到一些关注!您在问题中写的大部分内容都是正确的。如果您希望Beast在调用message::prepare_payload时设置Content-Length字段,则必须在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;
}