package route import ( "bytes" "git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/resource/config" "github.com/gin-gonic/gin" "hilo-user/myerr/bizerr" "hilo-user/req" "hilo-user/req/jwt" "hilo-user/resp" "io/ioutil" "runtime/debug" "strings" "time" ) /** controller层全局异常处理 */ // 等级最高,为了只为最后有返回值到前端 func ExceptionHandle(c *gin.Context) { defer func() { if r := recover(); r != nil { //打印错误堆栈信息 mylogrus.MyLog.Errorf("ExceptionHandle SYSTEM ACTION PANIC: %v, stack: %v", r, string(debug.Stack())) resp.ResponseErrWithString(c, r) //终止后续接口调用,不加的话recover到异常后,还会继续执行接口里后续代码 c.Abort() } }() c.Next() } // jwt解密 func JWTApiHandle(c *gin.Context) { logger := mylogrus.MyLog.WithField("URL", c.Request.URL).WithField("METHOD", c.Request.Method) token := c.GetHeader("token") if token == "" { logger.Warnf("token err is empty! %v", c.Request.Header) resp.ResponseBusiness(c, bizerr.TokenInvalid) c.Abort() return } claims, err := jwt.ParseToken(token) if err != nil { logger.Warnf("token parsed err:%v", err) resp.ResponseBusiness(c, bizerr.TokenInvalid) c.Abort() return } logger = logger.WithField("userId", claims.UserId) if time.Now().Unix() > claims.ExpiresAt { logger.Warnf("token expire err, now: %d, expiresAt %d", time.Now().Unix(), claims.ExpiresAt) resp.ResponseBusiness(c, bizerr.TokenInvalid) c.Abort() return } if claims.Issuer != config.GetConfigJWT().ISSUER_API { logger.Warnf("token err issuer:%s, configIssuer %s", claims.Issuer, config.GetConfigJWT().ISSUER_API) resp.ResponseBusiness(c, bizerr.TokenInvalid) c.Abort() return } var newToken = token // token 连续7天没玩,第八天回来后给新token(线上是30天过期) if claims.ExpiresAt-time.Now().Unix() < 86400*7 { logger.Infof("token nearly expire err, now:%d,expiresAt:%d", time.Now().Unix(), claims.ExpiresAt) newToken, err = jwt.GenerateToken(claims.UserId, claims.ExternalId, config.GetConfigJWT().ISSUER_API) if err != nil { logger.Warnf("token generation failed, err:%v", err) resp.ResponseBusiness(c, bizerr.TokenInvalid) c.Abort() return } } c.Set(mycontext.USERID, claims.UserId) c.Set(mycontext.EXTERNAL_ID, claims.ExternalId) c.Writer.Header().Add("token", newToken) c.Next() } // 日志Handle func LoggerHandle(c *gin.Context) { //开始时间 start := time.Now() clientIp := c.ClientIP() method := c.Request.Method traceId := genTraceId() reqUri := c.Request.RequestURI c.Set(mycontext.TRACEID, traceId) // header := c.Request.Header //类型 devicetype := header.Get("Devicetype") c.Set(mycontext.DEVICETYPE, devicetype) appVersion := header.Get("Appversion") c.Set(mycontext.APP_VERSION, appVersion) c.Set(mycontext.URL, reqUri) c.Set(mycontext.METHOD, method) userId, _ := req.GetUserId(c) bodyStr := "" contentType := c.Request.Header.Get("Content-Type") //文件就不打印 if strings.Index(contentType, "multipart/form-data") == -1 { data, err := c.GetRawData() if err != nil { mylogrus.MyLog.Errorf("handle log err:%v", err) } bodyStr = string(data) //很关键 //把读过的字节流重新放到body c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(data)) } mycontext.CreateMyContext(c.Keys).Log.Infof("request start traceId:%v, clientIp:%v, url:%v, method:%v, userId:%v, body:%v, header:%v", traceId, clientIp, reqUri, method, userId, bodyStr, header) //加载完 defer recover,继续后续接口调用 c.Next() end := time.Now() latency := end.Sub(start) mycontext.CreateMyContext(c.Keys).Log.Infof("request end fullPath:%v,url:%v, method: %v, traceId:%v, latency:%v userId:%v", c.FullPath(), reqUri, method, traceId, latency, userId) }