middleHandle.go 4.02 KB
Newer Older
hujiebin's avatar
hujiebin committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
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-group/myerr/bizerr"
	"hilo-group/req"
	"hilo-group/req/jwt"
	"hilo-group/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(c)
	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)
chenweijian's avatar
chenweijian committed
105 106 107 108 109 110
	lang := header.Get(mycontext.LANGUAGE)
	c.Set(mycontext.LANGUAGE, lang)
	carrier := header.Get(mycontext.CARRIER)
	c.Set(mycontext.CARRIER, carrier)
	timezone := header.Get(mycontext.TIMEZONE)
	c.Set(mycontext.TIMEZONE, timezone)
hujiebin's avatar
hujiebin committed
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135

	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)
}