如何使Protobuf 3字段成为强制性的?

问题描述 投票:0回答:2

我正在使用GRPCproto-buffers在GoLang中编写我的第一个API端点。下面是我为测试用例编写的文件。

package my_package

import (
    "context"
    "testing"

    "github.com/stretchr/testify/require"

    "google.golang.org/protobuf/types/known/structpb"
    "github.com/MyTeam/myproject/cmd/eventstream/setup"
    v1handler "github.com/MyTeam/myproject/internal/handlers/myproject/v1"
    v1interface "github.com/MyTeam/myproject/proto/.gen/go/myteam/myproject/v1"
)

func TestEndpoint(t *testing.T) {
    conf := &setup.Config{}

    // Initialize our API handlers
    myhandler := v1handler.New(&v1handler.Config{})

    t.Run("Success", func(t *testing.T) {
        res, err := myhandler.Endpoint(context.Background(), &v1interface.EndpointRequest{
            A: "S",
            B: &structpb.Struct{
                Fields: map[string]*structpb.Value{
                    "T": &structpb.Value{
                        Kind: &structpb.Value_StringValue{
                            StringValue: "U",
                        },
                    },
                    "V": &structpb.Value{
                        Kind: &structpb.Value_StringValue{
                            StringValue: "W",
                        },
                    },
                },
            },
            C: &timestamppb.Timestamp{Seconds: 1590179525, Nanos: 0},
        })
        require.Nil(t, err)

        // Assert we got what we want.
        require.Equal(t, "Ok", res.Text)
    })


}

这是如何 EndpointRequest 对象的定义是在 v1.go 文件包含在上面。

// An v1 interface Endpoint Request object.
message EndpointRequest {

  // a is something.
  string a = 1 [(validate.rules).string.min_len = 1];

  // b can be a complex object.
  google.protobuf.Struct b = 2;

  // c is a timestamp.
  google.protobuf.Timestamp c = 3;

}

上面的测试案例似乎可以正常工作。

我把验证规则放在了合适的位置,有效地使参数 a 强制性,因为它要求 a 是一个至少有一个的字符串。所以如果你省略了 a,端点返回400。

但现在我想确保在以下情况下,端点返回400。cb 被省略了。我怎么才能做到这一点?在Protobufs 3中,他们删除了 required 关键字。那么我如何检查是否有非字符串参数被传递进来,并做出相应的反应?

go protocol-buffers grpc-go
2个回答
5
投票

简而言之:你不能。

required 被删除的主要原因是它使更改向后不兼容。试图使用验证选项来重新实现它并没有那么激烈(变化更容易),但会遇到你所看到的缺点。

相反,将验证从proto定义中保留出来,并将其移入应用程序本身。每当你收到一个消息时,你应该检查它的内容(这也是当 required 是一个东西)。) 在极少数情况下,由选项或 required 是足够的。


3
投票

在下列情况下删除了必须填写的栏目 proto3. 这里是github问题 在这里你可以读到详细的解释,为什么这样做。这里是节选。

我们放弃了proto3中的必填字段 因为必填字段通常被认为是有害的 并且违反了protobuf的兼容性语义. 使用protobuf的整个想法是,它允许你从协议定义中添加删除字段,同时仍然完全向前向后兼容较新的二进制文件。但必填字段打破了这一点。你永远不能安全地在.proto定义中添加一个必填字段,也不能安全地删除一个现有的必填字段,因为这两个动作都破坏了线的兼容性。

IMO,这是一个有问题的决定,显然我不是一个人,谁的想法。最后的决定应该留给开发商。

© www.soinside.com 2019 - 2024. All rights reserved.