grpc proto 文件 字段验证
之前已经写了gRPC 和 gRPC gateway
今天把字段进行验证一下
上一篇文章链接
准备工作
- 安装
protoc-gen-validate - 引入
validate.proto - 生成
pb.validate.go - 调用验证器
安装
这里的安装和之前不太相同,git README 中给出是
go get -d-u 从网络下载,如果本地有了就不下载,然后安装 -d 只下载不安装
# 找到GOPATH
go env | grep GOPATH
# 在 GOPATH 中的 src下面进行go get -d
go get -d github.com/envoyproxy/protoc-gen-validate
引入validate/validate.proto
这个文件的路径在刚才go get -d的文件夹中
具体路径为$GOPATH/src/github.com/envoyproxy/protoc-gen-validate/validate
model.proto
syntax = "proto3";
package services;
option go_package = ".;services";
import "google/protobuf/timestamp.proto"; // 引入时间类型
import "validate/validate.proto"; // validate 三方库
// 商品模型
message ProdModel{
int32 prod_id = 1;
string prod_name = 2;
float prod_price = 3;
}
// 订单信息
message OrderInfo{
int32 order_id = 1; // 订单id
int32 order_no = 2; // 订单编号
int32 order_userId = 3; // 订单用户id
float order_price = 4 [(validate.rules).float.gt = 1]; // 订单金额,进行限制 大于0
google.protobuf.Timestamp order_time = 5;// 订单时间
repeated OrderDetail order_details = 6; // 拆分的一些订单
}
// 拆分订单
message OrderDetail{
int32 order_detail_id = 1; //拆分订单id
int32 order_detail_no = 2; //拆分订单号
int32 order_no = 3; // 主订单no
int32 order_type = 4; // 订单类型
int32 order_num = 5; // 订单物品数量
}
修改之前的genPb.sh 生成 pb.validate.go
cd pb \
&& protoc --go_out=../services --go_opt=paths=source_relative \
--go-grpc_out=../services --go-grpc_opt=paths=source_relative \
--validate_out=paths=source_relative,lang=go:../services \ # 生成pb.validate.go
Prod.proto Models.proto Orders.proto \
&& protoc -I . \
--grpc-gateway_out ../services/Gateway/ \
--grpc-gateway_opt logtostderr=true \
--grpc-gateway_opt paths=source_relative \
Prod.proto Models.proto Orders.proto
在gRPC接口实现中进行验证
// orderService.go
// 创建订单接口实现
func (o *OrderService)NewOrder(ctx context.Context,request *OrderRequest) (*OrderResponse, error){
req := request.OrderInfo
log.Println(req.OrderPrice,req.OrderNo,req.OrderId,req.OrderTime,req.OrderUserId)
// 参数校验
err := req.Validate()
if err != nil{
// 返回订单创建失败
return &OrderResponse{
Status: "error",
Msg: err.Error(),
},nil
}
//打印订单信息
for _, detail := range req.OrderDetails {
log.Println("mainOrderId",detail.OrderNo,"detailId:",detail.OrderDetailId,"detailNo:",detail.OrderDetailNo,"num:",detail.OrderNum,"type:",detail.OrderType)
}
// 返回订单创建结果
return &OrderResponse{
Status: "1",
Msg: "创建订单成功",
},nil
}
调用测试
别忘记 重新build grpc 和httpserver
curl --location --request POST 'http://localhost:23333/v1/createOrder' \
--header 'Content-Type: application/json' \
--data-raw '{
"order_id": 123,
"order_no": 321,
"order_userId": 12345,
"order_price": 0.5,
"order_time": "2017-01-15T01:30:15.01Z",
"order_details": [
{
"order_detail_id": 1,
"order_detail_no": 2,
"order_no": 3,
"order_type": 4,
"order_num": 5
},
{
"order_detail_id": 11,
"order_detail_no": 22,
"order_no": 33,
"order_type": 44,
"order_num": 55
}
]
}'
结果
{
"status": "error",
"msg": "invalid OrderInfo.OrderPrice: value must be greater than 1"
}