mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-02-03 02:54:41 +08:00
95 lines
2.6 KiB
Go
95 lines
2.6 KiB
Go
// Package tcp
|
|
// @Link https://github.com/bufanyun/hotgo
|
|
// @Copyright Copyright (c) 2023 HotGo CLI
|
|
// @Author Ms <133814250@qq.com>
|
|
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
|
package tcp
|
|
|
|
import (
|
|
"context"
|
|
"github.com/gogf/gf/v2/errors/gcode"
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
"github.com/gogf/gf/v2/text/gstr"
|
|
"reflect"
|
|
"runtime"
|
|
)
|
|
|
|
// RouteHandler 路由处理器
|
|
type RouteHandler struct {
|
|
Id string // 路由ID
|
|
IsRPC bool // 是否支持rpc协议
|
|
Func reflect.Value // 路由处理方法
|
|
Input reflect.Value // 输入参数
|
|
Output reflect.Value // 输出参数
|
|
}
|
|
|
|
// ParseRouteHandler 解析路由
|
|
func ParseRouteHandler(router interface{}, isRPC bool) (info *RouteHandler, err error) {
|
|
funcName := runtime.FuncForPC(reflect.ValueOf(router).Pointer()).Name()
|
|
funcType := reflect.ValueOf(router).Type()
|
|
|
|
if funcType.NumIn() != 2 {
|
|
err = gerror.Newf(ParseRouterErrInvalidParams, funcName)
|
|
return
|
|
}
|
|
|
|
if funcType.In(0) != reflect.TypeOf((*context.Context)(nil)).Elem() {
|
|
err = gerror.Newf(ParseRouterErrInvalidFirstParam, funcName)
|
|
return
|
|
}
|
|
|
|
inputType := funcType.In(1)
|
|
if !(inputType.Kind() == reflect.Ptr && inputType.Elem().Kind() == reflect.Struct) {
|
|
err = gerror.Newf(ParseRouterErrInvalidSecondParam, funcName)
|
|
return
|
|
}
|
|
|
|
// The request struct should be named as `xxxReq`.
|
|
if !gstr.HasSuffix(inputType.String(), `Req`) && !gstr.HasSuffix(inputType.String(), `Res`) {
|
|
err = gerror.NewCodef(
|
|
gcode.CodeInvalidParameter,
|
|
`invalid struct naming of the request: defined as "%s", but should be named with the "Req" or "Res" suffix, such as "XxxReq" or "XxxRes"`,
|
|
inputType.String(),
|
|
)
|
|
return
|
|
}
|
|
|
|
info = &RouteHandler{
|
|
Id: gstr.SubStrFromREx(inputType.String(), `.`),
|
|
IsRPC: isRPC,
|
|
Func: reflect.ValueOf(router),
|
|
Input: reflect.New(inputType.Elem()),
|
|
}
|
|
|
|
if !isRPC {
|
|
return
|
|
}
|
|
|
|
if funcType.NumOut() != 2 {
|
|
err = gerror.Newf(ParseRouterRPCErrInvalidParams, funcName)
|
|
return
|
|
}
|
|
outputType := funcType.Out(0)
|
|
// The response struct should be named as `xxxRes`.
|
|
if !gstr.HasSuffix(outputType.String(), `Res`) {
|
|
err = gerror.NewCodef(
|
|
gcode.CodeInvalidParameter,
|
|
`invalid struct naming for response: defined as "%s", but it should be named with "Res" suffix like "XxxRes"`,
|
|
outputType.String(),
|
|
)
|
|
return
|
|
}
|
|
|
|
if !funcType.Out(1).Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
|
err = gerror.NewCodef(
|
|
gcode.CodeInvalidParameter,
|
|
`invalid handler: defined as "%s", but the last output parameter should be type of "error"`,
|
|
reflect.TypeOf(funcType).String(),
|
|
)
|
|
return
|
|
}
|
|
|
|
info.Output = reflect.New(outputType.Elem())
|
|
return
|
|
}
|