我正在尝试实现一个包含已解析的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 生成用于传输的正文字节。我错了吗?
无论如何,你认为有一个很好的方法来解决这个问题吗?
提前感谢您的时间和精力!
此致 维拉德
答案 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;
}