feat: coco core support

This commit is contained in:
Young Xu 2023-03-19 00:49:46 +08:00
parent 03a3aae71b
commit b2ad24762a
Signed by: xuthus5
GPG Key ID: A23CF9620CBB55F9
3 changed files with 185 additions and 47 deletions

61
core/file_module.proto Normal file
View File

@ -0,0 +1,61 @@
syntax = "proto3";
package controller;
option go_package = "./;core";
// @route_group: true
// @base_url: /api/file
// @gen_to: ./core/file_controller.go
service File {
// @desc:
// @author: Young Xu
// @method: GET
// @api: /list
rpc List (ListReq) returns (ListResp);
// @desc:
// @author: Young Xu
// @method: POST
// @api: /upload
rpc Upload (UploadReq) returns (UploadResp);
// @desc:
// @author: Young Xu
// @method: POST
// @api: /delete
rpc Delete (DeleteReq) returns (DeleteResp);
// @desc:
// @author: Young Xu
// @method: GET
// @api: /download
rpc Download (DownloadReq) returns (DownloadResp);
}
message ListReq {}
message ListResp {
message Item {
string filename = 1; //
string file_size = 2; //
string created_at = 3; //
}
repeated Item items = 1; //
}
message UploadReq {}
message UploadResp {}
message DeleteReq {
string filename = 1; //
}
message DeleteResp {}
message DownloadReq {
// @v: required
string f = 1; //
}
message DownloadResp {}

View File

@ -4,7 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"reflect"
"runtime"
@ -31,6 +31,36 @@ type Result struct {
type Register struct {
// GET参数解析器
queryDecoder *schema.Decoder
engine *gin.Engine
addr string
}
type RegisterOptions func(register *Register)
// WithGinMode set gin router mode
func WithGinMode(mode string) RegisterOptions {
return func(register *Register) {
gin.SetMode(mode)
}
}
// WithRecovery returns a middleware that recovers from any panics and writes a 500 if there was one.
func WithRecovery() RegisterOptions {
return func(register *Register) {
register.engine.Use(gin.Recovery())
}
}
func WithCors() RegisterOptions {
return func(register *Register) {
register.engine.Use(CorsFilter())
}
}
func WithListenAddress(addr string) RegisterOptions {
return func(register *Register) {
register.addr = addr
}
}
// NewRegister 实例化注册器
@ -41,63 +71,79 @@ func NewRegister() *Register {
return register
}
func (r *Register) DefaultRouter(opts ...RegisterOptions) *Register {
r.engine = gin.New()
for _, option := range opts {
option(r)
}
return r
}
// RegisterStruct 按照 struct 的方法进行路由注册
// rout: gin路由 建议传入group 将公共的中间件传递入group中
// routers: 绑定自动生成的路由配置文件 proto同级的 autogen_router_module.go 文件中的 AutoGenXXXMap
// igs: 需要注册的API组的struct ptr
// ig: 需要注册的API组的struct ptr
// 对于错误或异常零容忍 直接panic
func (r *Register) RegisterStruct(rout gin.IRouter, routers Routers, igs ...interface{}) {
func (r *Register) RegisterStruct(routers *Routers, drv interface{}, mws ...gin.HandlerFunc) {
if len(routers.Apis) == 0 {
logrus.Warnf("%s api list empty, skip registe", routers.StructName)
logrus.Warnf("%s api list empty, skip register", routers.StructName)
return
}
if len(igs) == 0 {
panic("group struct empty")
if drv == nil {
logrus.Warnf("%s api struct nil, skip register", routers.StructName)
return
}
for _, ig := range igs {
//bind := ig.(BindGroupRouteSrv) // 你需要实现 BindGroupRouteSrv
// 输出一下 rg
refVal := reflect.ValueOf(ig)
refTyp := reflect.TypeOf(ig)
// new router group
if r.engine == nil {
r.DefaultRouter(WithGinMode(gin.ReleaseMode))
}
logrus.Infof("base url: %v", routers.BaseURL)
newRouter := r.engine.Group(routers.BaseURL, mws...)
//routConfig := r.routers[bind.Bind()]
//if routConfig == nil {
// panic("no func to register")
//}
//if routConfig.Apis == nil {
// panic("no func to register")
//}
// 注册路由公共中间件
//if len(routConfig.Middlewares) != 0 {
// r.registerMiddleware(rout, routConfig.Middlewares)
//}
routMap := routers.Apis
for m := 0; m < refTyp.NumMethod(); m++ {
// 这里取出方法
method := refTyp.Method(m)
//bind := ig.(BindGroupRouteSrv) // 你需要实现 BindGroupRouteSrv
// 输出一下 rg
refVal := reflect.ValueOf(drv)
refTyp := reflect.TypeOf(drv)
var node *RouterNode
var exist bool
if node, exist = routMap[method.Name]; !exist {
continue
}
if routers.BaseURL != "" {
node.API = routers.BaseURL + node.API
}
// 注册路由
if err := r.registerHandle(rout, node, method.Func, refVal); err != nil {
logrus.Errorf("err: %+v", err)
panic("err: " + err.Error())
}
//routConfig := r.routers[bind.Bind()]
//if routConfig == nil {
// panic("no func to register")
//}
//if routConfig.Apis == nil {
// panic("no func to register")
//}
// 注册路由公共中间件
//if len(routConfig.Middlewares) != 0 {
// r.registerMiddleware(rout, routConfig.Middlewares)
//}
routMap := routers.Apis
for m := 0; m < refTyp.NumMethod(); m++ {
// 这里取出方法
method := refTyp.Method(m)
var node *RouterNode
var exist bool
if node, exist = routMap[method.Name]; !exist {
continue
}
// 注册路由
if err := r.registerHandle(newRouter, node, method.Func, refVal); err != nil {
logrus.Errorf("err: %+v", err)
panic("err: " + err.Error())
}
}
}
// registerMiddleware 注册中间件
func (r *Register) registerMiddleware(router gin.IRouter, mws []gin.HandlerFunc) {
router.Use(mws...)
// Run 服务运行
func (r *Register) Run() {
if r.addr == "" {
r.addr = ":8080"
}
if err := r.engine.Run(r.addr); err != nil {
logrus.Errorf("run server failed: %v", err)
}
}
// registerHandle 注册Handle
@ -259,9 +305,9 @@ func (r *Register) getCallFunc(rFunc, rGroup reflect.Value) (gin.HandlerFunc, er
// bindAndValidate 绑定并校验参数
func (r *Register) bindAndValidate(c *gin.Context, req interface{}) error {
bodyBytes, _ := ioutil.ReadAll(c.Request.Body)
bodyBytes, _ := io.ReadAll(c.Request.Body)
c.Request.Body.Close()
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
// 校验
if c.Request.Method == http.MethodGet {
@ -312,3 +358,30 @@ func (r *Register) bindAndValidate(c *gin.Context, req interface{}) error {
return nil
}
// CorsFilter 跨域过滤器
func CorsFilter() gin.HandlerFunc {
return func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Headers", "*")
c.Header("Access-Control-Allow-Methods", "*")
c.Header("Access-Control-Expose-Headers", "*")
if c.Request.Method == "OPTIONS" {
c.String(http.StatusNoContent, "OPTIONS")
return
}
}
}
// ResponseJsonHeader 统一设置返回json格式数据
func ResponseJsonHeader() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Content-Type", "application/json")
}
}
func ResponseHtmlHeader() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Content-Type", "text/html")
}
}

View File

@ -2,6 +2,7 @@ package core
import (
"fmt"
"github.com/gin-gonic/gin"
"reflect"
"testing"
)
@ -25,6 +26,9 @@ func TestRegister_getCallFunc(t *testing.T) {
}
func TestNewRegister(t *testing.T) {
//var reg = NewRegister()
//reg.registerHandle()
var reg = NewRegister()
reg.DefaultRouter(WithGinMode(gin.DebugMode))
// protoc core/file_module.proto --coco_out=core --go_out=core
//reg.RegisterStruct(AutoGenFileRouterMap, &File{})
reg.Run()
}