Go gRPC服务proto数据验证进阶教程

作者:烟花易冷人憔悴 时间:2024-03-20 16:54:54 

前言

上篇介绍了go-grpc-middleware的grpc_zap、grpc_auth和grpc_recovery使用,本篇将介绍grpc_validator,它可以对gRPC数据的输入和输出进行验证。

创建proto文件,添加验证规则

这里使用第三方插件go-proto-validators自动生成验证规则。

go get github.com/mwitkow/go-proto-validators

1.新建simple.proto文件

syntax = "proto3";
package proto;
import "github.com/mwitkow/go-proto-validators/validator.proto";
message InnerMessage {
 // some_integer can only be in range (1, 100).
 int32 some_integer = 1 [(validator.field) = {int_gt: 0, int_lt: 100}];
 // some_float can only be in range (0;1).
 double some_float = 2 [(validator.field) = {float_gte: 0, float_lte: 1}];
}
message OuterMessage {
 // important_string must be a lowercase alpha-numeric of 5 to 30 characters (RE2 syntax).
 string important_string = 1 [(validator.field) = {regex: "^[a-z]{2,5}$"}];
 // proto3 doesn't have `required`, the `msg_exist` enforces presence of InnerMessage.
 InnerMessage inner = 2 [(validator.field) = {msg_exists : true}];
}
service Simple{
 rpc Route (InnerMessage) returns (OuterMessage){};
}

代码import "github.com/mwitkow/go-proto-validators/validator.proto",文件validator.proto需要import "google/protobuf/descriptor.proto";包,不然会报错。

google/protobuf地址:

https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto

把src文件夹中的protobuf目录下载到GOPATH目录下。

2.编译simple.proto文件

go get github.com/mwitkow/go-proto-validators/protoc-gen-govalidators

指令编译:

protoc --govalidators_out=. --go_out=plugins=grpc:./ ./simple.proto

或者使用VSCode-proto3插件,第一篇有介绍。只需要添加"--govalidators_out=."即可。

// vscode-proto3插件配置
   "protoc": {
       // protoc.exe所在目录
       "path": "C:\\Go\\bin\\protoc.exe",
       // 保存时自动编译
       "compile_on_save": true,
       "options": [
           // go编译输出指令
           "--go_out=plugins=grpc:.",
           "--govalidators_out=."
       ]
   },

编译完成后,自动生成simple.pb.go和simple.validator.pb.go文件,simple.pb.go文件不再介绍,我们看下simple.validator.pb.go文件。

// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: go-grpc-example/9-grpc_proto_validators/proto/simple.proto
package proto
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
_ "github.com/mwitkow/go-proto-validators"
regexp "regexp"
github_com_mwitkow_go_proto_validators "github.com/mwitkow/go-proto-validators"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
func (this *InnerMessage) Validate() error {
if !(this.SomeInteger > 0) {
return github_com_mwitkow_go_proto_validators.FieldError("SomeInteger", fmt.Errorf(`value '%v' must be greater than '0'`, this.SomeInteger))
}
if !(this.SomeInteger < 100) {
return github_com_mwitkow_go_proto_validators.FieldError("SomeInteger", fmt.Errorf(`value '%v' must be less than '100'`, this.SomeInteger))
}
if !(this.SomeFloat >= 0) {
return github_com_mwitkow_go_proto_validators.FieldError("SomeFloat", fmt.Errorf(`value '%v' must be greater than or equal to '0'`, this.SomeFloat))
}
if !(this.SomeFloat <= 1) {
return github_com_mwitkow_go_proto_validators.FieldError("SomeFloat", fmt.Errorf(`value '%v' must be lower than or equal to '1'`, this.SomeFloat))
}
return nil
}
var _regex_OuterMessage_ImportantString = regexp.MustCompile(`^[a-z]{2,5}$`)
func (this *OuterMessage) Validate() error {
if !_regex_OuterMessage_ImportantString.MatchString(this.ImportantString) {
return github_com_mwitkow_go_proto_validators.FieldError("ImportantString", fmt.Errorf(`value '%v' must be a string conforming to regex "^[a-z]{2,5}$"`, this.ImportantString))
}
if nil == this.Inner {
return github_com_mwitkow_go_proto_validators.FieldError("Inner", fmt.Errorf("message must exist"))
}
if this.Inner != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Inner); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Inner", err)
}
}
return nil
}

里面自动生成了message中属性的验证规则。

把grpc_validator验证 * 添加到服务端

grpcServer := grpc.NewServer(cred.TLSInterceptor(),
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
grpc_validator.StreamServerInterceptor(),
       grpc_auth.StreamServerInterceptor(auth.AuthInterceptor),
grpc_zap.StreamServerInterceptor(zap.ZapInterceptor()),
grpc_recovery.StreamServerInterceptor(recovery.RecoveryInterceptor()),
)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
   grpc_validator.UnaryServerInterceptor(),
   grpc_auth.UnaryServerInterceptor(auth.AuthInterceptor),
grpc_zap.UnaryServerInterceptor(zap.ZapInterceptor()),
           grpc_recovery.UnaryServerInterceptor(recovery.RecoveryInterceptor()),
)),
)

运行后,当输入数据验证失败后,会有以下错误返回

Call Route err: rpc error: code = InvalidArgument desc = invalid field SomeInteger: value '101' must be less than '100'

其他类型验证规则设置

enum验证

syntax = "proto3";
package proto;
import "github.com/mwitkow/go-proto-validators/validator.proto";
message SomeMsg {
 Action do = 1 [(validator.field) = {is_in_enum : true}];
}
enum Action {
 ALLOW = 0;
 DENY = 1;
 CHILL = 2;
}

UUID验证

syntax = "proto3";
package proto;
import "github.com/mwitkow/go-proto-validators/validator.proto";
message UUIDMsg {
 // user_id must be a valid version 4 UUID.
 string user_id = 1 [(validator.field) = {uuid_ver: 4, string_not_empty: true}];
}

来源:https://www.cnblogs.com/FireworksEasyCool/p/12761033.html

标签:Go,gRPC,proto,数据验证
0
投稿

猜你喜欢

  • 使用Nginx+uWsgi实现Python的Django框架站点动静分离

    2023-11-13 11:30:37
  • vue项目打包后怎样优雅的解决跨域

    2024-04-29 13:11:03
  • Python实现爬取逐浪小说的方法

    2022-05-26 22:31:29
  • 用Python自动发邮件提醒你周末吃啥

    2022-04-10 11:44:28
  • Python3 文章标题关键字提取的例子

    2022-02-08 03:45:32
  • 解决Vue大括号字符换行踩的坑

    2024-04-10 13:47:43
  • Python中常用的os操作汇总

    2022-12-13 08:30:16
  • 浅谈python和C语言混编的几种方式(推荐)

    2021-11-30 02:48:51
  • Typora 1.4.8激活 2022最新Typora破解激活使用教程

    2022-02-13 18:14:59
  • python列表排序用 sort()和sorted()的区别

    2021-11-27 10:36:20
  • Python多线程threading join和守护线程setDeamon原理详解

    2022-05-25 18:09:39
  • Django集成百度富文本编辑器uEditor攻略

    2021-01-11 21:43:21
  • Python内置函数 next的具体使用方法

    2023-09-30 18:42:28
  • python的多元数据类型(下)

    2023-06-17 02:45:11
  • SQL Server 触发器 表的特定字段更新时,触发Update触发器

    2024-01-25 09:32:20
  • sqlserver 不重复的随机数

    2024-01-14 00:13:59
  • Python编程基础之字典

    2021-10-02 13:34:56
  • Python入门教程4. 元组基本操作 <font color=red>原创</font>

    2021-01-12 09:53:21
  • 二维码的生成细节和原理

    2023-02-28 16:36:01
  • Python word实现读取及导出代码解析

    2021-05-11 07:56:47
  • asp之家 网络编程 m.aspxhome.com