127 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Package middleware ...
 | |
| //
 | |
| // Description : middleware ...
 | |
| //
 | |
| // Author : go_developer@163.com<白茶清欢>
 | |
| //
 | |
| // Date : 2022-07-14 10:53
 | |
| package middleware
 | |
| 
 | |
| import (
 | |
| 	"strings"
 | |
| 
 | |
| 	"git.zhangdeman.cn/zhangdeman/gin/request/parse_body"
 | |
| 	"git.zhangdeman.cn/zhangdeman/gin/util"
 | |
| 
 | |
| 	"git.zhangdeman.cn/zhangdeman/consts"
 | |
| 	"git.zhangdeman.cn/zhangdeman/gin/request"
 | |
| 	"go.uber.org/zap"
 | |
| 
 | |
| 	"git.zhangdeman.cn/zhangdeman/gin/define"
 | |
| 
 | |
| 	"git.zhangdeman.cn/zhangdeman/logger"
 | |
| 	"github.com/gin-gonic/gin"
 | |
| )
 | |
| 
 | |
| // fillCfg 填充默认配置
 | |
| func fillCfg(cfg *AccessConfig) {
 | |
| 	if nil == cfg {
 | |
| 		return
 | |
| 	}
 | |
| 	if nil == cfg.IsRecordLog {
 | |
| 		cfg.IsRecordLog = defaultIsRecordLog
 | |
| 	}
 | |
| 	if nil == cfg.RequestHeaderList {
 | |
| 		cfg.RequestHeaderList = make([]string, 0)
 | |
| 	}
 | |
| 	if nil == cfg.ResponseHeaderList {
 | |
| 		cfg.ResponseHeaderList = make([]string, 0)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // getLogRequestHeader 获取记录的请求header
 | |
| func getLogRequestHeader(ctx *gin.Context, cfg *AccessConfig) map[string][]string {
 | |
| 	// 请求header
 | |
| 	headerTable := make(map[string][]string)
 | |
| 	if len(cfg.RequestHeaderList) == 0 {
 | |
| 		// 全部记录
 | |
| 		for headerKey := range ctx.Request.Header {
 | |
| 			cfg.RequestHeaderList = append(cfg.RequestHeaderList, headerKey)
 | |
| 		}
 | |
| 	}
 | |
| 	for _, key := range cfg.RequestHeaderList {
 | |
| 		headerTable[key] = ctx.Request.Header.Values(key)
 | |
| 	}
 | |
| 	return headerTable
 | |
| }
 | |
| 
 | |
| // getLogResponseHeader 记录相应header
 | |
| func getLogResponseHeader(ctx *gin.Context, cfg *AccessConfig) map[string][]string {
 | |
| 	// 响应header
 | |
| 	responseHeaderTable := make(map[string][]string)
 | |
| 	if len(cfg.ResponseHeaderList) == 0 {
 | |
| 		// 全部记录
 | |
| 		for headerKey := range ctx.Writer.Header() {
 | |
| 			cfg.ResponseHeaderList = append(cfg.ResponseHeaderList, headerKey)
 | |
| 		}
 | |
| 		zap.Any("pkg_gin_response_header", ctx.Writer.Header())
 | |
| 	}
 | |
| 	for _, key := range cfg.ResponseHeaderList {
 | |
| 		responseHeaderTable[key] = ctx.Writer.Header().Values(key)
 | |
| 	}
 | |
| 	return responseHeaderTable
 | |
| }
 | |
| 
 | |
| // LogRequest 记录请求日志
 | |
| func LogRequest(cfg *AccessConfig) gin.HandlerFunc {
 | |
| 	fillCfg(cfg)
 | |
| 	handleConfig := define.GetHttpHandleConfig()
 | |
| 	return func(ctx *gin.Context) {
 | |
| 		// 未传入配置或者未传入日志实例
 | |
| 		if nil == cfg || nil == cfg.Logger || (nil != cfg.IsRecordLog && !cfg.IsRecordLog(ctx)) {
 | |
| 			ctx.Next()
 | |
| 			return
 | |
| 		}
 | |
| 		startRequestTime := request.WrapperHandle.GetCtxIntData(ctx, handleConfig.StartRequestTimeField, 0)
 | |
| 		// 记录请求日志
 | |
| 		data := map[string]any{
 | |
| 			handleConfig.StartRequestTimeField: startRequestTime,                      // 开始请求时间
 | |
| 			"request_header":                   getLogRequestHeader(ctx, cfg),         // 请求header
 | |
| 			"request_query":                    request.WrapperHandle.ParseQuery(ctx), // 获取请求query
 | |
| 			"request_body":                     map[string]any{},                      // 请求body
 | |
| 		}
 | |
| 		data["request_body"], _ = parse_body.ExecuteForMap(ctx)
 | |
| 		logData := logger.NewLogData(util.GinCtxToContext(ctx), consts.LogTypeRequest, "", data)
 | |
| 		cfg.Logger.Info("接口请求日志记录", logData.ToFieldList()...)
 | |
| 		ctx.Next()
 | |
| 		// 结束时间
 | |
| 		finishRequestTime := request.WrapperHandle.GetCtxIntData(ctx, handleConfig.FinishRequestTimeField, 0)
 | |
| 		ctx.Set(handleConfig.FinishRequestTimeField, finishRequestTime)
 | |
| 		// 记录相应日志
 | |
| 		logResponseData := logger.NewLogData(util.GinCtxToContext(ctx), consts.LogTypeOutput, "", map[string]any{
 | |
| 			handleConfig.FinishRequestTimeField: finishRequestTime,                                                                            // 完成请求时间
 | |
| 			"request_cost":                      finishRequestTime - startRequestTime,                                                         // 请求耗时
 | |
| 			"response_body":                     request.WrapperHandle.GetResponseBody(ctx, handleConfig.ResponseDataField, map[string]any{}), // 响应body
 | |
| 			"response_header":                   getLogResponseHeader(ctx, cfg),                                                               // 响应header
 | |
| 		})
 | |
| 		if ctx.GetBool(define.GetHttpHandleConfig().RequestIsSuccessField) {
 | |
| 			cfg.Logger.Info("接口响应日志记录", logResponseData.ToFieldList()...)
 | |
| 		} else {
 | |
| 			cfg.Logger.Error("接口响应日志记录", logResponseData.ToFieldList()...)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // AccessConfig 访问记录的配置
 | |
| type AccessConfig struct {
 | |
| 	Logger             *zap.Logger                 // 日志实例
 | |
| 	RequestHeaderList  []string                    // 要记录哪些header , 不传全部记录
 | |
| 	ResponseHeaderList []string                    // 要记录哪些响应header, 不传全部记录
 | |
| 	IsRecordLog        func(ctx *gin.Context) bool // 验证当前请求是否记录日志
 | |
| }
 | |
| 
 | |
| // defaultIsRecordLog 默认仅记录 json api 日志
 | |
| func defaultIsRecordLog(ctx *gin.Context) bool {
 | |
| 	return strings.Contains(ctx.Writer.Header().Get(consts.HeaderKeyContentType.String()), "application/json")
 | |
| }
 |