go-common/app/tool/bmproto/README.md

276 lines
7.6 KiB
Markdown
Raw Normal View History

2019-04-22 10:49:16 +00:00
# 目录
<!-- vim-markdown-toc GitLab -->
* [简介](#简介)
* [HTTP访问](#http访问)
* [grpc](#grpc)
* [安装](#安装)
* [用法](#用法)
* [生成结果](#生成结果)
* [命名规范](#命名规范)
* [proto包名与版本号](#proto包名与版本号)
* [生成的go文件的包名](#生成的go文件的包名)
* [多个proto文件](#多个proto文件)
* [其他特性](#其他特性)
* [添加http框架的Middleware](#添加http框架的middleware)
* [自定义Url或者指定http方法为post](#自定义url或者指定http方法为post)
* [生成service模板](#生成service模板)
* [form tag和json tag](#form-tag和json-tag)
* [指定输入参数的约束条件](#指定输入参数的约束条件)
* [同步Markdown文档到live-doc仓库直播Only](#同步markdown文档到live-doc仓库直播only)
* [支持json做为输入](#支持json做为输入)
* [直播部门老的用法](#直播部门老的用法)
* [兼容直播服务列表按照discovery id](#兼容直播服务列表按照discovery-id)
<!-- vim-markdown-toc -->
## 简介
根据protobuf文件生成grpc和blademaster框架http代码及文档
```protobuf
syntax = "proto3";
package department.app;
option go_package = "api";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
service Greeter{
// api 标题
// api 说明
rpc SayHello(HelloRequest) returns (HelloResponse);
}
message HelloRequest {
// 请求参数说明
string param1 = 1 [(gogoproto.moretags) = 'form:"param1"'];
}
message HelloResponse {
// 返回字段说明
string ret_string = 1 [(gogoproto.jsontag) = 'ret_string'];
}
```
#### HTTP访问
```
GET /department.app.Greeter/SayHello?param1=p1
响应
{
"code": 0,
"message": "ok",
"data": {
"ret_string": "anything"
}
}
```
#### grpc
路径 /department.app.Greeter/SayHello
## 安装
```shell
go install go-common/app/tool/bmproto/...
```
## 用法
- cd 项目目录
- 在 api目录下新建api.proto文件(参见上面的例子) 例如 api/api.proto
- 运行 bmgen在项目的任意位置
- 创建 internal/service/greeter.go(这是写业务代码的地方)也可以通过bmgen -t直接生成
```go
import pb "path-to-project/api"
....
// 实现 pb.GreeterBMServer 和 grpc的 pb.GreeterServer
type GreeterService struct {
}
func (s *GreeterService) SayHello(ctx context.Context, req *pb.SayHelloRequest)
(resp *pb.SayHelloResp, err error) {
}
```
- 在server/http.go 初始化代码(一般是`route`方法)里加入代码
```go
import pb "path-to-project/api"
import svc "path-to-project/internal/service"
......
pb.RegisterGreeterBMServer(engine, &svc.GreeterService{})
```
- 如果是grpc 在server/grpc/server.go 初始化里面加入代码
`pb.RegisterGreeterServer(grpcServer, &svc.GreeterService{})`
- 启动服务
- 访问接口 `curl 127.0.0.1:8000/department.app.Greeter/SayHello` (默认路由规则为 `/package.service/method`)
### 生成结果
```
project-
|------|--internal/service/greeter.go (使用bmgen -t 会生成如果proto新增加方法会自动往这里面添加模板代码
|--api/
|--api.greeter.md (HTTP API文档)
|--api.bm.go
|--api.pb.go
|--api.proto
```
## 命名规范
### proto包名与版本号
- DISCOVERY_ID 或者 DISCOVERY_ID.v*
- DISCOVERY_ID的构成为 `部门.服务` 并且去掉中划线
- 第一个版本不用加版本号从第二个版本加v2
- **示例** 部门 department 服务 hello-world 则 package为`department.helloworld`, 文件目录为api/
- 第二个版本package `department.helloworld.v2", 目录为api/v2
### 生成的go文件的包名
- golang一般原则上保持包名和目录名一致
- proto 可以指定`option go_package = "xxx"; `
比如对于api/api.proto `option go_package = "api"; `
对于api/v2/api.proto `option go_package = "v2"; `
### 多个proto文件
一个文件夹下面可以有多个proto文件但是要满足以下约束
- 同目录下的proto package 一致
- message service 等定义不能重复因为是在统一package下面
## 其他特性
### 添加http框架的Middleware
在RegisterXXBMServer之前加入代码
```
bm.Inject(pb.PathGreeterSayHello, middleware1, middleware2)
```
### 自定义Url或者指定http方法为post
```protobuf
.....
package department.app;
....
import "google/api/annotations.proto";
....
service Greeter{
rpc SayHelloCustomUrl(HelloRequest) returns (HelloResponse) {
option (google.api.http) = {
get:"/say_hello" // GET /say_hello
};
};
rpc SayHelloPost(HelloRequest) returns (HelloResponse) {
option (google.api.http) = {
post:"" // POST /department.app.Greeter/SayHelloPost
};
};
}
```
### 生成service模板
`bmgen -t` 生成service模板代码在 internal/service/serviceName.go
### form tag和json tag
```
对于HTTP接口
现在请求字段需要加上form tag以解析请求参数
响应参数需要加上json tag 以避免 字段为0或者空字符串时不显示
这两个tag都建议和字段名保持一致
现在是必须加将来考虑维护一个自己的proto仓库以移除这个多余的tag
```
### 指定输入参数的约束条件
```protobuf
...
import "github.com/gogo/protobuf/gogoproto/gogo.proto"
...
message Request {
int param1 = 1 [(gogoproto.moretags) = 'validate:"required"')]; // 参数必传不能等于0
}
```
### 同步Markdown文档到live-doc仓库直播Only
`bmgen -l`
### 支持json做为输入
```
curl 127.0.0.1:8000/department.app.Greeter/SayHello -H "Content-Type: application/json" -d "{"param1":"p1"}" -X POST
```
## 直播部门老的用法
**对于以下"兼容直播服务列表中的服务"有效**
- URL/xlive/项目名/v*/service开头小写/method
- 注册路由使用RegisterXXXService而不是 RegisterXXBMServer
- middleware不支持RegisterXXXMiddleware 而是 使用注解
```go
api/api.proto
service Greeter {
// `method:"POST"` // 表示请求方法为POST
// `midware:"user"`
rpc SayHello(A) returns (B);
}
// server/http/http.go
import bm "go-common/library/net/http/blademaster"
....
userAuthMiddleware := xxxxx
pb.RegisterXXService(e, svc, map[string]bm.HandlerFunc{"user":userAuthMiddleware})
```
- 注解,在方法或者字段上方的注视添加和 go的tag格式一样的注解实现一定的功能
注解列表:
| key | 位置 | 说明 |
| ------------ | --------------------- | ------------------------------------------------------------ |
| midware | rpc method上方 | midware:"auth,verify" 中间件auth 是验证登录态verify是校验签名 |
| method | rpc method上方 | method:"POST" 指定http请求方法 |
| mock | 响应message的字段上方 | mock:"mockdata" mock数据生成文档的时候有用 |
| internal | 不建议继续使用 | 不建议继续使用 |
| dynamic | 不建议继续使用 | 不建议继续使用 |
| dynamic_resp | 不建议继续使用 | 不建议继续使用 |
### 兼容直播服务列表按照discovery id
- "live.webucenter"
- "live.webroom"
- "live.appucenter"
- "live.appblink"
- "live.approom"
- "live.appinterface"
- "live.liveadmin"
- "live.resource"
- "live.livedemo"
- "live.lotteryinterface"