前言

上篇介绍了go-grpc-middlewaregrpc_zapgrpc_authgrpc_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/tree/master/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.gosimple.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}];
}

总结

go-grpc-middlewaregrpc_validator集成go-proto-validators,我们只需要在编写proto时设好验证规则,并把grpc_validator添加到gRPC服务端,就能完成gRPC的数据验证,很简单也很方便。

教程源码地址:https://github.com/Bingjian-Zhu/go-grpc-example

最新文章

  1. jQuery链式操作[转]
  2. NOI 题库 8465
  3. PDF.NET框架学习篇之SQL-MAP使用存储过程
  4. Android工程师入门(二)——不忙不累怎么睡。。
  5. canvas API ,通俗的canvas基础知识(五)
  6. PHP实现浏览历史记录
  7. SQL 如何表示引号
  8. BZOJ 1646: [Usaco2007 Open]Catch That Cow 抓住那只牛( BFS )
  9. BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式( 二分答案 + 后缀数组 )
  10. html练习(5)
  11. Java日志工具之java.util.logging.Logger
  12. SignUtil
  13. RabbitMQ 官方demo1
  14. SSH报错
  15. SQL 查看表每一个列的名字以及类型
  16. hostapd作为radius服务器
  17. win10系统下载-靠谱推荐
  18. matlab中find函数的使用说明
  19. 重写UITableViewCell子类中属性的setter方法来实现隐藏或显示该cell中的某些控件
  20. css position:absolute align center bottom

热门文章

  1. # Unity 游戏框架搭建 2019 (十六、十七) localPosition 简化与Transform 重置
  2. Spring Boot 邮件发送
  3. Java 注解 So Easy!!!
  4. 解决pycharm不能导入bs4模块问题
  5. RPC框架实现(一) Protobuf的rpc实现
  6. 使用Git pull文件时,出现&quot;error: RPC failed; curl 18 transfer closed with outstanding read data remaining&quot;
  7. iOS 缩小 ipa 大小
  8. SimpleITK 和 Nibabel 读取医学图像 nii 数据(2D显示)
  9. 面向对象(OO)第一阶段学习总结
  10. IntelliJ IDEA 激活码 [已购买,分享给码友]