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

前言

上篇介绍了go-grpc-middleware的grpc_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/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.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

以上就是Go gRPC服务proto数据验证进阶教程的详细内容,更多关于Go gRPC服务proto数据验证的资料请关注我们其它相关文章!

(0)

相关推荐

  • Go gRPC进阶教程服务超时设置

    目录 前言 客户端请求设置超时时间 服务端判断请求是否超时 运行结果 总结 前言 gRPC默认的请求的超时时间是很长的,当你没有设置请求超时时间时,所有在运行的请求都占用大量资源且可能运行很长的时间,导致服务资源损耗过高,使得后来的请求响应过慢,甚至会引起整个进程崩溃. 为了避免这种情况,我们的服务应该设置超时时间. 前面的入门教程 Go gRPC环境安装教程示例详解 Go gRPC教程实现Simple RPC Go gRPC服务端流式RPC教程示例 Go gRPC服务客户端流式RPC教程 Go

  • Go gRPC服务客户端流式RPC教程

    目录 前言 情景模拟:客户端大量数据上传到服务端 新建proto文件 创建Server端 创建Client端 思考 总结 前言 上一篇介绍了服务端流式RPC,客户端发送请求到服务器,拿到一个流去读取返回的消息序列. 客户端读取返回的流的数据.本篇将介绍客户端流式RPC. 客户端流式RPC:与服务端流式RPC相反,客户端不断的向服务端发送数据流,而在发送结束后,由服务端返回一个响应. 情景模拟:客户端大量数据上传到服务端 新建proto文件 新建client_stream.proto文件 1.定义

  • Go gRPC服务双向流式RPC教程

    目录 前言 情景模拟 新建proto文件 创建Server端 创建Client端 总结 前言 上一篇介绍了客户端流式RPC,客户端不断的向服务端发送数据流,在发送结束或流关闭后,由服务端返回一个响应.本篇将介绍双向流式RPC. 双向流式RPC:客户端和服务端双方使用读写流去发送一个消息序列,两个流独立操作,双方可以同时发送和同时接收. 情景模拟 双方对话(可以一问一答.一问多答.多问一答,形式灵活). 新建proto文件 新建both_stream.proto文件 1.定义发送信息 // 定义流

  • golang 微服务之gRPC与Protobuf的使用

    RPC是什么? 所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型.使用的时候客户端调用server端提供的接口就像是调用本地的函数一样. gRPC是什么? 与许多RPC系统一样,gRPC基于定义服务的思想,指定可以使用其参数和返回类型远程调用的方法.默认情况下,gRPC使用协议缓冲区作为接口定义语言(IDL)来描述服务接口和有效负载消息的结构. gRPC有什么好处以及在什么场景下

  • Go gRPC服务端流式RPC教程示例

    目录 前言 情景模拟:实时获取股票走势 新建proto文件 创建Server端 创建Client端 思考 总结 前言 上一篇介绍了简单模式RPC,当数据量大或者需要不断传输数据时候,我们应该使用流式RPC,它允许我们边处理边传输数据.本篇先介绍服务端流式RPC. 服务端流式RPC:客户端发送请求到服务器,拿到一个流去读取返回的消息序列. 客户端读取返回的流,直到里面没有任何消息. 情景模拟:实时获取股票走势 1.客户端要获取某原油股的实时走势,客户端发送一个请求 2.服务端实时返回该股票的走势

  • go实现grpc四种数据流模式

    目录 2.1 简单模式 2.2 服务端数据流模式 2.3 客户端数据流模式 2.4 双向数据流 3.1 代码目录 3.2 编写stream.proto文件 3.3 编写server文件 3.4 编写client文件 1. 什么是数据流 grpc中的stream,srteam顾名思义就是一种流,可以源源不断的推送数据,很适合传输一些大数据,或者服务端和客户端长时间数据交互,比如客户端可以向服务端订阅一个数据,服务端就可以利用stream,源源不断地推送数据. 底层还原成socket编程 2. gr

  • golang下grpc框架的使用编写示例

    目录 1. 什么是grpc和protobuf 1.1 grpc 1.2 protobuf 2.go下grpc 2.1官网下载protobuf工具 2.2 下载go的依赖包 2.3 编写proto文件 2.4 生成hello.pb.proto文件 2.5 编写server端代码 2.6 编写client端代码 2.7 python和go相互调用实践(跨语言调用) 1. 什么是grpc和protobuf 1.1 grpc gRPC是一个高性能.开源和通用的RPC框架,面向移动和HTTP/2设计. 目

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

    前言 上篇介绍了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"; pa

  • Go gRPC服务进阶middleware使用教程

    目录 前言 go-grpc-middleware简介 grpc_zap日志记录 grpc_auth认证 grpc_recovery恢复 总结 前言 之前介绍了gRPC中TLS认证和自定义方法认证,最后还简单介绍了gRPC拦截器的使用.gRPC自身只能设置一个拦截器,所有逻辑都写一起会比较乱.本篇简单介绍go-grpc-middleware的使用,包括grpc_zap.grpc_auth和grpc_recovery. go-grpc-middleware简介 go-grpc-middleware封

  • Go gRPC进阶教程gRPC转换HTTP

    目录 前言 gRPC转成HTTP 编写和编译proto 服务端代码修改 使用postman测试 生成swagger文档 把swagger-ui转成Go代码,备用 对外提供swagger-ui 在swagger中配置bearer token 验证测试 总结 前言 我们通常把RPC用作内部通信,而使用Restful Api进行外部通信.为了避免写两套应用,我们使用grpc-gateway把gRPC转成HTTP.服务接收到HTTP请求后,grpc-gateway把它转成gRPC进行处理,然后以JSON

  • 如何在.NET Core中为gRPC服务设计消息文件(Proto)

    如何在.NET Core中为gRPC服务设计消息 使用协议缓冲区规范定义gRPC服务非常容易,但从需求转换为.NET Core,然后管理服务的演变时,需要注意几件事. 创建gRPC服务的核心是.proto文件,该文件以与语言无关的格式描述了该服务.使用.proto文件,Visual Studio可以为您的服务生成基类(您只需编写特定于业务的代码),或者可以生成用于可靠访问服务的客户端类. .proto文件必须符合Google的协议缓冲区规范(通常称为ProtoBuf).原始文件的内容使您可以指定

  • Win2003下cwRsyncServer服务端与cwRsync客户端数据同步实例教程

    说明: cwRsyncServer服务端   IP:192.168.21.128 cwRsync客户端   IP:192.168.21.129 实现目的: 把服务端D:\data目录中的数据通过任务计划定期同步到客户端D:\data目录中 附件: cwRsyncServer下载地址与cwRsync下载地址:http://s.jb51.net 具体操作: 一.在服务端安装cwRsyncServer 解压cwRsyncServer_4.0.3_Installer.zip,双击cwRsyncServe

  • 用Python编写简单的gRPC服务的详细过程

    gRPC 是可以在任何环境中运行的现代开源高性能 RPC 框架.它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务,以实现负载平衡,跟踪,运行状况检查和身份验证.它也适用于分布式计算的最后一英里,以将设备,移动应用程序和浏览器连接到后端服务. 用Python编写简单的gRPC服务 grpc官网python参考:https://www.grpc.io/docs/languages/python/quickstart/ http://grpc.github.io/grpc/python/

随机推荐