https://github.com/envoyproxy/protoc-gen-validate
https://github.com/mwitkow/go-proto-validators
This project is currently in alpha. The API should be considered unstable and likely to change
PGV is a protoc plugin to generate polyglot message validators. While protocol buffers effectively guarantee the types of structured data, they cannot enforce semantic rules for values. This plugin adds support to protoc-generated code to validate such constraints.
Developers import the PGV extension and annotate the messages and fields in their proto files with constraint rules:
syntax = “proto3”;
package examplepb;
import “validate/validate.proto”;
message Person {
uint64 id = 1 [(validate.rules).uint64.gt = 999];
string email = 2 [(validate.rules).string.email = true];
string name = 3 [(validate.rules).string = {
pattern: “^[^[0-9]A-Za-z]+( [^[0-9]A-Za-z]+)*$”,
max_bytes: 256,
}];
Location home = 4 [(validate.rules).message.required = true];
message Location {
double lat = 1 [(validate.rules).double = { gte: -90, lte: 90 }];
double lng = 2 [(validate.rules).double = { gte: -180, lte: 180 }];
}
}
Executing protoc with PGV and the target language’s default plugin will create Validate methods on the generated types:
p := new(Person)
err := p.Validate() // err: Id must be greater than 999
p.Id = 1000
err = p.Validate() // err: Email must be a valid email address
p.Email = “example@lyft.com”
err = p.Validate() // err: Name must match pattern ‘^[^\d\s]+( [^\d\s]+)*$’
p.Name = “Protocol Buffer”
err = p.Validate() // err: Home is required
p.Home = &Location{37.7, 999}
err = p.Validate() // err: Home.Lng must be within [-180, 180]
p.Home.Lng = -122.4
err = p.Validate() // err: nil
This project is currently in alpha. The API should be considered unstable and likely to change
PGV is a protoc plugin to generate polyglot message validators. While protocol buffers effectively guarantee the types of structured data, they cannot enforce semantic rules for values. This plugin adds support to protoc-generated code to validate such constraints.
Developers import the PGV extension and annotate the messages and fields in their proto files with constraint rules:
syntax = “proto3”;
package examplepb;
import “validate/validate.proto”;
message Person {
uint64 id = 1 [(validate.rules).uint64.gt = 999];
string email = 2 [(validate.rules).string.email = true];
string name = 3 [(validate.rules).string = {
pattern: “^[^[0-9]A-Za-z]+( [^[0-9]A-Za-z]+)*$”,
max_bytes: 256,
}];
Location home = 4 [(validate.rules).message.required = true];
message Location {
double lat = 1 [(validate.rules).double = { gte: -90, lte: 90 }];
double lng = 2 [(validate.rules).double = { gte: -180, lte: 180 }];
}
}
Executing protoc with PGV and the target language’s default plugin will create Validate methods on the generated types:
p := new(Person)
err := p.Validate() // err: Id must be greater than 999
p.Id = 1000
err = p.Validate() // err: Email must be a valid email address
p.Email = “example@lyft.com”
err = p.Validate() // err: Name must match pattern ‘^[^\d\s]+( [^\d\s]+)*$’
p.Name = “Protocol Buffer”
err = p.Validate() // err: Home is required
p.Home = &Location{37.7, 999}
err = p.Validate() // err: Home.Lng must be within [-180, 180]
p.Home.Lng = -122.4
err = p.Validate() // err: nil
tar -zxvf go1.13.4.linux-amd64.tar.gz
1
2
3
1.2 配置go环境
编辑 /etc/profile 文件
vim ~/.bashrc
1
将下面内容加入到末尾(GOPAT是我Windows中的GOPATH)
export GOROOT=/usr/local/go
export GOPATH=/home/pibigstar/goWork
export PATH=$GOPATH/bin:$PATH
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
1
2
3
4
unzip protoc.zip
1
将bin文件夹下的 protoc 复制到Linux 中的 /bin目录下
sudo cp protoc/bin/protoc /bin/protoc
1
执行 protoc -verson 如果输出版本信息则证明配置成功
2.2 安装protoc-gen-go
git clone https://github.com/golang/protobuf.git
cd protobuf/protoc-gen-go
go install
1
2
3
4
5
6
2.3 安装protoc-gen-validate
这个是用来生成pb的校验规则文件,也就是*.pb.validate.go
go get -u github.com/envoyproxy/protoc-gen-validate
1
2.4 安装protoc-gen-grpc-gateway
这个是用来生成让grpc支持http调用的
git clone https://github.com/grpc-ecosystem/grpc-gateway.git
cd grpc-gateway/protoc-gen-grpc-gateway
go install .
cd grpc-gateway/protoc-gen-swagger
go install .
1
2
3
4
5
6
7
2.5 安装protoc-gen-doc
这个是用来生成 proto 的文档文件,会生成一个 html 格式的文档, 下载地址:https://github.com/pseudomuto/protoc-gen-doc/releases
wget https://github.com/pseudomuto/protoc-gen-doc/releases/download/v1.3.0/protoc-gen-doc-1.3.0.windows-amd64.go1.11.2.tar.gz
tar -zxvf protoc-gen-doc-1.3.0.windows-amd64.go1.11.2.tar.gz
1
2
3
4
2.6 安装proto-gen-java
可在这个地址下载 protoc-gen-java工具,https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/ ,记得把文件名改为protoc-gen-grpc-java.exe
syntax=”proto3”;
package main;
message Hello {
string value = 1;
}
1
2
3
4
5
6
7
3.2 编译
3.2.1 编译为Go代码(protoc-gen-go)
protoc –go_out=plugins=grpc,paths=source_relative:. –validate_out=”lang=go,paths=source_relative:.” hello.proto
1
注意
paths参数
使用 source_relative 则不会使用option go_package中指定的路径
使用 import 则是使用option go_package 中指定的路径
3.2.2 编译为Java代码 (protoc-gen-java)
可在这个地址下载 protoc-gen-java工具,https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/1.0.1/ ,记得把文件名改为protoc-gen-grpc-java.exe
protoc –java_out=. –grpc-java_out=. hello.proto
1
3.2.3 生成proto文档(proto-gen-doc)
protoc –doc_out=. –doc_opt=html,index.html:Ignore* hello.proto user.proto
1
3.3 复杂点的proto
syntax=”proto3”;
//生成的pb文件中package为admin
package admin;
//生成go文件的路径
option go_package = “pb/admin”;
//关闭Java多文件
option java_multiple_files = false;
//生成的Java文件的package路径
option java_package = “pb.admin”;
service UserService {
rpc Login(LoginReq) returns (LoginResp);
}
message LoginReq {
string username = 1;
string password = 2;
}
message LoginResp {
int32 code = 1;
string msg = 2;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
3.4 生成gw.pb文件
proto 导入 google/api/annotations.proto
syntax = “proto3”;
package pb;
option go_package = “pb/echo”;
import “google/api/annotations.proto”;
service Echo {
rpc UnaryEcho (EchoRequest) returns (EchoResponse){
option (google.api.http) = {
post: “/v1/example/echo”
body: “*”
};
}
}
// EchoRequest is the request for echo.
message EchoRequest {
string message = 1;
}
// EchoResponse is the response for echo.
message EchoResponse {
string message = 1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
下载地址: https://github.com/googleapis/googleapis/tree/master/google
在proto下面将 google的api 放进去
在这里插入图片描述
编译时用 -I 命令 引入 extra/src 下面的文件
protoc -I=extra/src:.
–grpc-gateway_out=logtostderr=true:pb
–go_out=plugins=grpc,paths=import:pb echo.proto
1
2
3
3.5 编译脚本
#!/usr/bin/env bash
TARGET=”../”
if [ -n “$1” ]; then
TARGET=$1
fi
for file in find . -path ./extra/src -prune -o -name '*.proto' -print
;
do
echo $file
protoc -I=extra/src:. –grpc-gateway_out=$TARGET
–go_out=plugins=grpc,paths=import:$TARGET
–validate_out=”lang=go,paths=import:$TARGET” $file
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
3.6 代码注册
package main
import (
“github.com/grpc-ecosystem/grpc-gateway/runtime”
“golang.org/x/net/context”
“google.golang.org/grpc”
“net/http”
pb "data/proto/demo/echo" )
func main() {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
mux := runtime.NewServeMux()
opts := []grpc.DialOption{grpc.WithInsecure()}
err := pb.RegisterEchoHandlerFromEndpoint(ctx, mux, "127.0.0.1:6000", opts)
if err != nil {
return err
}
http.ListenAndServe(":8080", mux) }