package router import ( "bp.jydev.jianyu360.cn/BaseService/gateway/common/db" "bp.jydev.jianyu360.cn/BaseService/gateway/common/enum" . "bp.jydev.jianyu360.cn/BaseService/gateway/common/gatecode" "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/net/gtrace" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/util/gconv" "log" "regexp" "strings" ) type Manager struct { eqRouters map[string]*Router regexRouter map[*regexp.Regexp]*Router } // InitRouterManager 初始化系统代理路由 // 支持完全匹配和正则匹配 func InitRouterManager() (*Manager, error) { //无权限地址 urlSwitch := g.Cfg().MustGet(gctx.New(), "noPowerUrlSwitch").MapStrStr() //加载规则 res := db.GateWatMySql.Query(fmt.Sprintf("SELECT status,middleground_code,url,function_code,check_sess,check_power,check_auth,check_status,check_blacklist,ploy_code,timeout,remark,appid,deduct_source,power_type FROM %s", g.Cfg().MustGet(gctx.New(), "system.routerTable", "front_proxy").String())) if res == nil || len(*res) == 0 { return nil, fmt.Errorf("未发现可用路由") } // 初始化 routerManager routerManager := &Manager{ eqRouters: make(map[string]*Router), regexRouter: make(map[*regexp.Regexp]*Router), } for _, row := range *res { // 获取路由信息 router := gconv.String(row["url"]) signCode := gconv.String(row["middleground_code"]) routerRule := &Router{ Status: gconv.Int(row["status"]), PowerCheck: gconv.Int(row["check_power"]), SessCheck: enum.NewSessCheck(gconv.Int64(row["check_sess"])), AccountCheck: enum.NewAccountCheck(gconv.Int64(row["check_status"])), AuthCheck: enum.NewAuthCheck(gconv.Int64(row["check_auth"])), BlackCheck: gconv.Int(row["check_blacklist"]) == 1, LimitPloy: gconv.String(row["ploy_code"]), //策略 Deduct: gconv.Int(row["deduct_source"]), FuncCode: gconv.String(row["function_code"]), MiddleCode: signCode, AppId: gconv.String(row["appid"]), ReqUrl: router, IsOutServer: strings.HasPrefix(signCode, "http://") || strings.HasPrefix(signCode, "https://"), TimeOut: gconv.Int64(row["timeout"]), Remark: gconv.String(row["remark"]), PowerType: gconv.Int(row["power_type"]), NoPowerUrl: urlSwitch[router], } // 判断路由匹配方式是完全匹配还是正则匹配 (此处逻辑参考x-web框架) if regexp.QuoteMeta(router) == router { routerManager.eqRouters[router] = routerRule } else { reg, err := regexp.Compile(router) if err != nil { log.Printf("路由%s装载异常 %v\n", router, err) } routerManager.regexRouter[reg] = routerRule } } return routerManager, nil } // GetRouterRule 获取路由规则 // 根据用户请求地址匹配路由规则,优先绝对匹配后用正则匹配。 func (m *Manager) GetRouterRule(url string) (*Router, error) { routerRule, exists := m.eqRouters[url] if !exists { for reg, thisRouterRule := range m.regexRouter { if reg.MatchString(url) { routerRule = thisRouterRule break } } } if routerRule == nil { return nil, NewErrorWithCode(GATEWAY_ROUTER_NOTFIND, fmt.Sprintf("未找到请求地址%s,请检查是否注册到数据库\n", url)) } // 路由状态判断 if routerRule.Status != 1 { return nil, NewErrorWithCode(GATEWAY_ROUTER_UPHOLD, fmt.Sprintf("接口状态:%d\n", routerRule.Status)) } return routerRule, nil } // InfusionContext 注入通用结构体gContext func (m *Manager) InfusionContext(r *ghttp.Request) (err error) { _, span := gtrace.NewSpan(r.Context(), "InfusionContext") defer span.End() //r.SetCtx(ctx) var router *Router var GCtx = &GContext{ Sess: &JySession{}, RouterRule: &Router{}, } router, err = m.GetRouterRule(r.URL.Path) if err != nil { r.SetCtxVar(GContextKey, GCtx) return } GCtx.RouterRule = router //获取session jySess, _ := InitJySessionContext(r) GCtx.Sess = jySess r.SetCtxVar(GContextKey, GCtx) return }