go-common/app/tool/bmproto/README.md
2019-04-22 18:49:16 +08:00

276 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 目录
<!-- 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"