通过 protobuf 自动生成 bm server,统一数据传输模型.
go install go-common/app/tool/protoc-gen-bm
# 生成 examples/helloworld bm server 代码
protoc -I. -Ithird_party/googleapis --bm_out=:. examples/helloworld/api/v1/helloworld.proto
# 使用 jsonpb
protoc -I. -Ithird_party/googleapis --bm_out=jsonpb=true:. examples/helloworld/api/v1/helloworld.proto
service Messaging {
rpc GetMessage(GetMessageRequest) returns (Message) {
option (google.api.http) = {
get: "/message";
};
}
}
message GetMessageRequest {
string name = 1; // Mapped to URL path.
}
message Message {
string text = 1; // The resource content.
}
http 到 gRPC 的映射如下
HTTP | gRPC |
---|---|
GET /message?name=foo |
GetMessage(name: "foo") |
对于 GET 之类不包含 Body 的请求,所有的 Request Message 将被映射到 URL Query 中。
对于嵌套的字段通过 .
分割 例如:
service Messaging {
rpc GetMessage(GetMessageRequest) returns (Message) {
option (google.api.http) = {
get:"/messages"
};
}
}
message GetMessageRequest {
message SubMessage {
string subfield = 1;
}
string message_id = 1;
int64 revision = 2;
SubMessage sub = 3;
}
HTTP | gRPC |
---|---|
GET /messages?message_id=123456&revision=2&sub.subfield=foo |
GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: "foo")) |
对于包含 Body 的 http 请求,body 字段可以用来指定数据映射
service Messaging {
rpc CreateMessage(CreateMessageRequest) returns (Message) {
option (google.api.http) = {
post: "/messages"
body: "*"
};
}
}
message CreateMessageRequest {
string message_id = 1;
string text = 2;
}
HTTP | gRPC |
---|---|
POST /v1/messages {"message_id": "123456", "text": "Hi!" } |
CreateMessage(message_id: "123456", text: "Hi!") |
Json Response
{
"code": 0,
"message": "this is message",
"data": {// Response Message Marshal as JSON}
}
Protobuf Response
message PB {
int64 Code = 1;
string Message = 2;
uint64 TTL = 3;
google.protobuf.Any Data = 4;
}
目前自动生成的 BUILD 的文件无法正常编译,需要手动修改,以 example/helloworld 项目为例,需要对 BUILD 文件进行以下修改
--- a/app/tool/protoc-gen-bm/examples/helloworld/api/v1/BUILD
+++ b/app/tool/protoc-gen-bm/examples/helloworld/api/v1/BUILD
@@ -13,8 +13,8 @@ load(
proto_library(
name = "v1_proto",
srcs = ["helloworld.proto"],
- tags = ["automanaged"],
- deps = ["google/api/annotations.proto"],
+ tags = ["manual"],
+ deps = ["@go_googleapis//google/api:annotations_proto"],
)
go_proto_library(
@@ -22,14 +22,14 @@ go_proto_library(
compilers = ["@io_bazel_rules_go//proto:go_grpc"],
importpath = "go-common/app/tool/protoc-gen-bm/examples/helloworld/api/v1",
proto = ":v1_proto",
- tags = ["automanaged"],
- deps = ["google/api/annotations.proto"],
+ tags = ["manual"],
+ deps = ["@go_googleapis//google/api:annotations_go_proto"],
)
go_library(
name = "go_default_library",
srcs = ["helloworld.pb.bm.go"],
- embed = ["v1_go_proto"],
+ embed = [":v1_go_proto"],
importpath = "go-common/app/tool/protoc-gen-bm/examples/helloworld/api/v1",
tags = ["automanaged"],
visibility = ["//visibility:public"],
恩、不解释了,应该都能看懂
因为 blademaster 在 Bind parameters 时默认是大小写敏感的,而且没有自动转换驼峰与下划线,所以在定义 Proto message 时需要用 gogo 自定义一些 tag
message User {
// mid
int64 mid = 1 [(gogoproto.moretags) = "form:\"mid\" validate:\"required,min=1\""];
}
参考 https://github.com/gogo/protobuf/blob/master/extensions.md
TODO
TODO
/cc @liugang @zhoujiahui