未检查/强制执行 Protobuf C++ 必填字段
Posted
技术标签:
【中文标题】未检查/强制执行 Protobuf C++ 必填字段【英文标题】:Protobuf C++ required fields are not checked/enforced 【发布时间】:2017-05-17 06:44:40 【问题描述】:我是 Protocol Buffers 的新手,目前我看到以下问题:
我们将proto2
语法与Protocol Buffers 3.2.0 库一起使用,并观察到required
字段在序列化期间未强制执行。
这里有一个 Catch C++ 测试的基本示例:
syntax = "proto2";
package simple_test;
message SimpleMessage
required string field1 = 1;
required string field2 = 2;
#include "simple.pb.h"
#include <catch.hpp>
#include <string>
SCENARIO("Verify that serialization with missing required fields fails", "[protobuf]")
GIVEN("a message")
simple_test::SimpleMessage m;
WHEN("field1 is set and field2 is not and both are required")
m.set_field1("aaa");
THEN("serializing this message to string buffer must fail")
std::string buffer;
CHECK_FALSE(m.SerializeToString(&buffer));
REQUIRE(buffer.empty());
m.SerializeToString(&buffer)
返回true
并且buffer.empty()
是false
。
我知道的
required
字段已在 Protobuf v3 中删除。
我的问题
我是否可以使用 Protobuf v3 强制执行这些检查的设置或任何类型的配置开关?用例会发生什么:
proto2
使用 Protobuf v3 编译器编译的消息。此消息以部分填写的必填字段结束,并将发送到强制执行 required
字段的 Protobuf v2 端点。这是否实际上意味着只发送了字节,因为消息无效并且将被拒绝?
我应该从 v3.2.0 降级到 2.x 以禁止在客户端发送不完整的消息吗?
【问题讨论】:
【参考方案1】:我带来了这份我之前监督过的文档:
Standard Message Methods 并且有以下文档:
标准消息方法
每个消息类还包含许多其他方法,可让您检查或操作整个消息,包括:
bool IsInitialized() const;
:检查是否所有必填字段都已设置。
这就是我需要的! Protobuf 再次很棒!
【讨论】:
【参考方案2】:我是否可以使用 Protobuf v3 强制执行这些检查的设置或任何类型的配置开关?
您是否尝试过在调试配置中构建 protobuf?我想你会发现它会在这种情况下断言。
用例会发生什么:
proto2 使用 Protobuf v3 编译器编译的消息。此消息以部分填写的必填字段结束,并将发送到强制执行必填字段的 Protobuf v2 enpoint。这是否实际上意味着只发送了字节,因为消息无效并且将被拒绝?
在这种情况下,接收者可以ParsePartialFromXXX
接收发送的内容。他可以用message.has_xxx()
测试消息的有效性
我应该从 v3.2.0 降级到 2.x 以禁止在客户端发送不完整的消息吗?
我不会。也许为每种消息类型编写一个检查器来断言每个必填字段都存在。更好的是,以 proto3 方式考虑它,并将缺失的字段视为接收器中的默认值。 protobuf 文档建议永远不要将 required
字段添加到现有消息类型,并建议在创建字段 required
之前“仔细考虑”。您可以将其理解为“糟糕,必填字段的概念是错误的”。
【讨论】:
感谢您的回复,即使它对 Protobuf 变异的方式令我失望。调试模式不是一个选项,即使我发现它断言比什么?关于其他两个问题,我阅读了必填字段,在我们的案例中,我不想拥有任何灵活的协议。这应该是“我的方式或高速公路”。我还读到,即使在谷歌,也有两个阵营在支持required
并反对它。
@ovanes 我知道这对我们 c++ 人来说很失望——我们已经习惯了强类型。但是当然protobuf最终只是一个序列化协议。服务器/接收者必须是正确与否的最终仲裁者。恶意客户端可以发送任何内容。因此,在我们的 protobuf rpc 实现中,服务器会检查所有不变量,如果消息格式错误或不完整,则返回异常通知。
是的,但这也违反了 DRY。有多少人使用 Protobuf 并且所有人都必须实施这种required
检查。我了解是否有人需要检查更复杂的不变量,例如该字段的值 X 是否比另一个应该具有 Y。但是如果有 required
这样的东西它也应该工作:(而不是问:是的!只是膨胀您的代码包含大量 if 语句并进行检查。AFAIK Protobuf 甚至不支持访问者模式,在没有 if
s 的情况下进行这种调度和验证。
@ovanes 您可以遍历消息描述符的字段描述符并检查是否需要,因此您可以使用一个引用基类Message
的函数检查所有消息@以上是关于未检查/强制执行 Protobuf C++ 必填字段的主要内容,如果未能解决你的问题,请参考以下文章