2023-01-14 16:29:52 +08:00
|
|
|
|
package req
|
2021-03-24 17:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
import (
|
2023-11-07 21:05:21 +08:00
|
|
|
|
"context"
|
|
|
|
|
|
"mayfly-go/pkg/biz"
|
|
|
|
|
|
"mayfly-go/pkg/contextx"
|
2024-02-25 12:46:18 +08:00
|
|
|
|
"mayfly-go/pkg/errorx"
|
2024-11-20 22:43:53 +08:00
|
|
|
|
"mayfly-go/pkg/i18n"
|
2024-02-25 12:46:18 +08:00
|
|
|
|
"mayfly-go/pkg/logx"
|
2022-06-02 17:41:11 +08:00
|
|
|
|
"mayfly-go/pkg/model"
|
|
|
|
|
|
"mayfly-go/pkg/utils/assert"
|
2024-02-24 16:30:29 +08:00
|
|
|
|
"net/http"
|
2021-04-21 10:22:09 +08:00
|
|
|
|
"time"
|
2021-03-24 17:18:39 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
2021-04-16 15:10:07 +08:00
|
|
|
|
// 处理函数
|
2023-01-14 16:29:52 +08:00
|
|
|
|
type HandlerFunc func(*Ctx)
|
2021-04-16 15:10:07 +08:00
|
|
|
|
|
2023-01-14 16:29:52 +08:00
|
|
|
|
type Ctx struct {
|
2024-02-25 12:46:18 +08:00
|
|
|
|
*wrapperF // http framework处理接口
|
|
|
|
|
|
Conf *Conf // 请求配置
|
2023-07-08 20:05:55 +08:00
|
|
|
|
|
2024-02-24 16:30:29 +08:00
|
|
|
|
ReqParam any // 请求参数,主要用于记录日志
|
|
|
|
|
|
ResData any // 响应结果
|
|
|
|
|
|
Error any // 请求错误
|
|
|
|
|
|
timed int64 // 执行时间
|
2023-11-07 21:05:21 +08:00
|
|
|
|
|
|
|
|
|
|
MetaCtx context.Context // 元数据上下文信息,如登录账号(只有校验token后才会有值),traceId等
|
2021-03-24 17:18:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-02-25 12:46:18 +08:00
|
|
|
|
func NewCtx(f F) *Ctx {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
metaCtx := contextx.WithTraceId(f.GetRequest().Context())
|
|
|
|
|
|
metaCtx = i18n.NewCtxWithLang(metaCtx, f.GetRequest().Header.Get("Accept-Language"))
|
|
|
|
|
|
|
|
|
|
|
|
ctx := &Ctx{MetaCtx: metaCtx}
|
2024-02-25 12:46:18 +08:00
|
|
|
|
ctx.wrapperF = NewWrapperF(f)
|
|
|
|
|
|
return ctx
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 执行指定handler func,并输出响应结果
|
2023-01-14 16:29:52 +08:00
|
|
|
|
func (rc *Ctx) Handle(handler HandlerFunc) {
|
2023-09-02 17:24:18 +08:00
|
|
|
|
begin := time.Now()
|
2021-04-16 15:10:07 +08:00
|
|
|
|
defer func() {
|
2023-09-02 17:24:18 +08:00
|
|
|
|
rc.timed = time.Since(begin).Milliseconds()
|
2021-04-16 15:10:07 +08:00
|
|
|
|
if err := recover(); err != nil {
|
2024-02-24 16:30:29 +08:00
|
|
|
|
rc.Error = err
|
2021-04-16 15:10:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
// 应用所有请求后置处理器
|
2021-05-08 18:00:33 +08:00
|
|
|
|
ApplyHandlerInterceptor(afterHandlers, rc)
|
2024-02-25 12:46:18 +08:00
|
|
|
|
// 输出响应结果
|
|
|
|
|
|
rc.res()
|
2021-04-16 15:10:07 +08:00
|
|
|
|
}()
|
2024-02-25 12:46:18 +08:00
|
|
|
|
assert.IsTrue(rc.wrapperF != nil, "F == nil")
|
2021-04-16 15:10:07 +08:00
|
|
|
|
|
|
|
|
|
|
// 默认为不记录请求参数,可在handler回调函数中覆盖赋值
|
2023-01-14 16:29:52 +08:00
|
|
|
|
rc.ReqParam = nil
|
2021-04-16 15:10:07 +08:00
|
|
|
|
// 默认响应结果为nil,可在handler中赋值
|
|
|
|
|
|
rc.ResData = nil
|
|
|
|
|
|
|
|
|
|
|
|
// 调用请求前所有处理器
|
2021-05-08 18:00:33 +08:00
|
|
|
|
err := ApplyHandlerInterceptor(beforeHandlers, rc)
|
2021-04-16 15:10:07 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
panic(err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
handler(rc)
|
2021-03-24 17:18:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-07 21:05:21 +08:00
|
|
|
|
// 获取当前登录账号信息,不存在则会报错。
|
|
|
|
|
|
//
|
|
|
|
|
|
// 若不需要报错,则使用contextx.GetLoginAccount方法
|
|
|
|
|
|
func (rc *Ctx) GetLoginAccount() *model.LoginAccount {
|
|
|
|
|
|
la := contextx.GetLoginAccount(rc.MetaCtx)
|
|
|
|
|
|
biz.IsTrue(la != nil, "获取登录账号信息失败, 请确认该接口是否通过鉴权")
|
|
|
|
|
|
return la
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-07-08 20:05:55 +08:00
|
|
|
|
func (rc *Ctx) WithConf(conf *Conf) *Ctx {
|
|
|
|
|
|
rc.Conf = conf
|
|
|
|
|
|
return rc
|
2021-04-16 15:10:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-07-08 20:05:55 +08:00
|
|
|
|
// 设置请求上下文需要的权限信息
|
|
|
|
|
|
func (rc *Ctx) WithRequiredPermission(permission *Permission) *Ctx {
|
|
|
|
|
|
if rc.Conf == nil {
|
|
|
|
|
|
rc.Conf = new(Conf)
|
|
|
|
|
|
}
|
|
|
|
|
|
rc.Conf.requiredPermission = permission
|
|
|
|
|
|
return rc
|
2021-03-24 17:18:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-07-08 20:05:55 +08:00
|
|
|
|
// 设置请求日志信息
|
|
|
|
|
|
func (rc *Ctx) WithLog(logInfo *LogInfo) *Ctx {
|
|
|
|
|
|
if rc.Conf == nil {
|
|
|
|
|
|
rc.Conf = new(Conf)
|
|
|
|
|
|
}
|
|
|
|
|
|
rc.Conf.logInfo = logInfo
|
|
|
|
|
|
return rc
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (rc *Ctx) GetLogInfo() *LogInfo {
|
|
|
|
|
|
return rc.Conf.logInfo
|
2021-06-09 16:58:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-02-25 12:46:18 +08:00
|
|
|
|
// 输出响应结果
|
|
|
|
|
|
func (rc *Ctx) res() {
|
|
|
|
|
|
if err := rc.Error; err != nil {
|
|
|
|
|
|
switch t := err.(type) {
|
2024-10-23 17:30:05 +08:00
|
|
|
|
case *errorx.BizError:
|
2024-02-25 12:46:18 +08:00
|
|
|
|
rc.JSONRes(http.StatusOK, model.Error(t))
|
|
|
|
|
|
default:
|
|
|
|
|
|
logx.ErrorTrace("服务器错误", t)
|
|
|
|
|
|
rc.JSONRes(http.StatusOK, model.ServerError())
|
|
|
|
|
|
}
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if rc.Conf == nil || !rc.Conf.noRes {
|
|
|
|
|
|
rc.JSONRes(http.StatusOK, model.Success(rc.ResData))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-02-24 16:30:29 +08:00
|
|
|
|
/************************************/
|
|
|
|
|
|
/***** GOLANG.ORG/X/NET/CONTEXT -> copy gin.Context *****/
|
|
|
|
|
|
/************************************/
|
|
|
|
|
|
|
|
|
|
|
|
// hasRequestContext returns whether c.Request has Context and fallback.
|
|
|
|
|
|
func (c *Ctx) hasRequestContext() bool {
|
2024-02-25 12:46:18 +08:00
|
|
|
|
request := c.GetRequest()
|
2024-02-24 16:30:29 +08:00
|
|
|
|
return request != nil && request.Context() != nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Deadline returns that there is no deadline (ok==false) when c.Request has no Context.
|
|
|
|
|
|
func (c *Ctx) Deadline() (deadline time.Time, ok bool) {
|
|
|
|
|
|
if !c.hasRequestContext() {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2024-02-25 12:46:18 +08:00
|
|
|
|
return c.GetRequest().Context().Deadline()
|
2024-02-24 16:30:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Done returns nil (chan which will wait forever) when c.Request has no Context.
|
|
|
|
|
|
func (c *Ctx) Done() <-chan struct{} {
|
|
|
|
|
|
if !c.hasRequestContext() {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
2024-02-25 12:46:18 +08:00
|
|
|
|
return c.GetRequest().Context().Done()
|
2024-02-24 16:30:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Err returns nil when c.Request has no Context.
|
|
|
|
|
|
func (c *Ctx) Err() error {
|
|
|
|
|
|
if !c.hasRequestContext() {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
2024-02-25 12:46:18 +08:00
|
|
|
|
return c.GetRequest().Context().Err()
|
2024-02-24 16:30:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Value returns the value associated with this context for key, or nil
|
|
|
|
|
|
// if no value is associated with key. Successive calls to Value with
|
|
|
|
|
|
// the same key returns the same result.
|
|
|
|
|
|
func (c *Ctx) Value(key any) any {
|
|
|
|
|
|
if key == 0 {
|
2024-02-25 12:46:18 +08:00
|
|
|
|
return c.GetRequest()
|
2024-02-24 16:30:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
if !c.hasRequestContext() {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
2024-02-25 12:46:18 +08:00
|
|
|
|
return c.GetRequest().Context().Value(key)
|
2021-03-24 17:18:39 +08:00
|
|
|
|
}
|
2021-05-08 18:00:33 +08:00
|
|
|
|
|
|
|
|
|
|
// 处理器拦截器函数
|
2023-01-14 16:29:52 +08:00
|
|
|
|
type HandlerInterceptorFunc func(*Ctx) error
|
2021-05-08 18:00:33 +08:00
|
|
|
|
type HandlerInterceptors []HandlerInterceptorFunc
|
|
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
|
beforeHandlers HandlerInterceptors
|
|
|
|
|
|
afterHandlers HandlerInterceptors
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// 使用前置处理器函数
|
|
|
|
|
|
func UseBeforeHandlerInterceptor(b HandlerInterceptorFunc) {
|
|
|
|
|
|
beforeHandlers = append(beforeHandlers, b)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 使用后置处理器函数
|
|
|
|
|
|
func UseAfterHandlerInterceptor(b HandlerInterceptorFunc) {
|
|
|
|
|
|
afterHandlers = append(afterHandlers, b)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 应用指定处理器拦截器,如果有一个错误则直接返回错误
|
2023-06-01 12:31:32 +08:00
|
|
|
|
func ApplyHandlerInterceptor(his HandlerInterceptors, rc *Ctx) any {
|
2021-05-08 18:00:33 +08:00
|
|
|
|
for _, handler := range his {
|
|
|
|
|
|
if err := handler(rc); err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|