package middleware import ( "encoding/json" "errors" "finclip-app-manager/infrastructure/client/httpcall" "fmt" "github.com/patrickmn/go-cache" "net/http" "strings" //"sync" "time" "gitlab.finogeeks.club/finclip-backend/apm" "github.com/gin-gonic/gin" "github.com/zzfup/go-fetch" ) var ( commonRsp CommonRspData commonConfig CommonConfigData //需要模糊匹配的url needSkipUrlList = []string{"/api/v1/mop/finstore/ruleEngine/app"} //确定的url needSkipUrlMap = map[string]bool{ "/ready": true, "/down": true, "/test": true, } ) type CommonConfigData struct { Error string `json:"error"` Errcode string `json:"errcode"` Data struct { OrganName string `json:"organName"` } `json:"data"` } type CommonRspData struct { Error string `json:"error"` Errcode string `json:"errcode"` } func getCommonConfig(c *gin.Context) error { var headers = map[string]string{ "Accept": "application/json, text/plain, */*", "Content-Type": "application/json", "Connection": "close", } options := fetch.Options{ Method: "GET", Header: headers, } url := "http://mop-private-init-server:8080/api/v1/mop/mop-private-init-server/common/config" spanId := c.Request.Header.Get("Zipkin-Span-Id") value := c.GetString("zipkin_trace_span_id_" + spanId) options.Header["Zipkin-Span-Context"] = value rsp, err := fetch.Fetch(url, options) if err != nil || rsp.StatusCode != 200 { return errors.New("mop-private-init-server err") } rsp.BindJSON(&commonConfig) return nil } var licenseCache = cache.New(time.Hour, time.Minute) //var licenseUrlMutex sync.Mutex //var licenseMutex sync.Mutex func CheckLicenseUrl(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) reqUrl := c.Request.URL.Path if isNotNeedCheckLicenseConfUrl(reqUrl) { c.Next() return } type CheckUrlReq struct { Url string `json:"url"` Method string `json:"method"` } //文件名只拉取一次 if commonConfig.Data.OrganName == "" { getCommonConfig(c) } var req CheckUrlReq req.Url = reqUrl req.Method = c.Request.Method licenseCacheKey := "license_url_status_" + reqUrl if code, ok := licenseCache.Get(licenseCacheKey); ok { if code.(int) != 200 { rspJson := gin.H{ "error": "license检测失败", "errcode": "MOP_LICENSE_FORBINDDEN", "data": nil, } c.AbortWithStatusJSON(http.StatusForbidden, rspJson) return } c.Next() return } //licenseUrlMutex.Lock() //defer licenseUrlMutex.Unlock() if code, ok := licenseCache.Get(licenseCacheKey); ok { if code.(int) != 200 { rspJson := gin.H{ "error": "license检测失败", "errcode": "MOP_LICENSE_FORBINDDEN", "data": nil, } c.AbortWithStatusJSON(http.StatusForbidden, rspJson) return } c.Next() return } var headers = map[string]string{ "Accept": "application/json, text/plain, */*", "Content-Type": "application/json", "Organ-Name": commonConfig.Data.OrganName, //私有化部署的时候,需要修改机构名称 "Connection": "close", } url := "http://mop-license-checker:8080/api/v1/mop/mop-license-checker/check/url" rsp, err := httpcall.NewClient().Request(traceCtx).SetHeaders(headers).SetBody(req).Post(url) if err != nil || rsp.StatusCode() != 200 { if err != nil { log.Errorf("check license url err:%+v", err) rspJson := gin.H{ "error": "license检测失败", "errcode": "MOP_LICENSE_FORBINDDEN", "data": nil, } c.AbortWithStatusJSON(http.StatusForbidden, rspJson) return } else { licenseCache.Set(licenseCacheKey, rsp.StatusCode(), 5*time.Minute) } json.Unmarshal(rsp.Body(), &commonRsp) fmt.Printf("license code no 200 code=%d,rsp=%+v\n", rsp.StatusCode, rsp) rspJson := gin.H{ "error": commonRsp.Error, "errcode": commonRsp.Errcode, "data": nil, } c.AbortWithStatusJSON(http.StatusForbidden, rspJson) return } licenseCache.Set(licenseCacheKey, rsp.StatusCode(), 5*time.Minute) c.Next() } func CheckLicenseConf(c *gin.Context) { url := c.Request.URL.Path if isNotNeedCheckLicenseConfUrl(url) { c.Next() return } licenseCacheKey := "license_exp" if code, ok := licenseCache.Get(licenseCacheKey); ok { if code.(int) != 1 { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "操作失败,当前环境license已过期", "errcode": "MOP_LICENSE_EXPIRED", "data": make(map[string]interface{}), }) return } c.Next() return } //licenseMutex.Lock() //defer licenseMutex.Unlock() if code, ok := licenseCache.Get(licenseCacheKey); ok { if code.(int) != 1 { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "操作失败,当前环境license已过期", "errcode": "MOP_LICENSE_EXPIRED", "data": make(map[string]interface{}), }) return } c.Next() return } traceCtx := apm.ApmClient().TraceContextFromGin(c) licenseInfo, err := hcaller.GetLicense(traceCtx) if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ "error": "license 请求错误", "errcode": "NET_ERROR", "data": make(map[string]interface{}), }) return } if licenseInfo.ExpireTime < time.Now().UnixNano()/1e6 { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "操作失败,当前环境license已过期", "errcode": "MOP_LICENSE_EXPIRED", "data": make(map[string]interface{}), }) licenseCache.Set(licenseCacheKey, 0, 5*time.Minute) return } licenseCache.Set(licenseCacheKey, 1, 5*time.Minute) } func isNotNeedCheckLicenseConfUrl(path string) bool { if _, ok := needSkipUrlMap[path]; ok { return true } for _, v := range needSkipUrlList { if strings.Contains(path, v) { return true } } return false }