Dra-M Dra-M
首页
技术
冥思
哲学
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

莫小龙

保持理智,相信未来。
首页
技术
冥思
哲学
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java

  • Golang

    • GitLab私服+Go Modules踩坑经验(SSH自定义端口)
    • 【代码片段】我使用的Gin中间处理器(自定义异常处理、日志打印、traceId、跨域配置)
    • 【Java转Go】如何理解Go中的值类型、引用类型、nil
    • 【Java转Go】如何理解面向对象,怎么把Golang用成面向对象的样子
    • Golang 调度器 GMP 原理与调度全分析
    • Go中GMP有哪些状态?
    • 一文搞懂go gc垃圾回收原理
    • Go什么时候发生阻塞?阻塞时,调度器会怎么做?
    • Go netpoller 原生网络模型之源码全面揭秘
    • Goroutine 泄露 - 被遗忘的发送者
    • go map 设计与实现
    • go slice 设计与实现
    • 小白也能看懂的context包详解:从入门到精通
    • go interface 设计与实现
    • 深入理解 go chan
    • go chan 设计与实现
    • 深入理解 go Mutex
    • 深入理解 go sync.Map - 基本原理
    • go sync.Map 设计与实现
    • 深入理解 go sync.Once
    • 深入理解 go reflect - 反射基本原理
    • 深入理解 go reflect - 要不要传指针
  • 编程思想

  • 微服务

  • 中间件

  • Python

  • 运维

  • 技术
  • Golang
莫小龙
2022-12-03

【代码片段】我使用的Gin中间处理器(自定义异常处理、日志打印、traceId、跨域配置)

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	uuid "github.com/satori/go.uuid"
	"net"
	"net/http"
	"os"
	"soul_station/src/common/response"
	"soul_station/src/global"
	"soul_station/src/startup/initialize/router"
	"strings"
)

func Router() {
	gin.SetMode(gin.ReleaseMode)
	apiEngine := newEngine()

	// API group
	api := apiEngine.Group("/api")
	//管理端
	router.AdminClient(api)
	//用户端
	router.UserClient(api)

	// 启动、监听端口
	_ = apiEngine.Run(fmt.Sprintf("localhost:%s", global.Config.Server.Port))

}

func newEngine() *gin.Engine {
	engine := gin.Default()
	//去掉默认handlers,去掉gin自带的日志打印
	engine.Handlers = nil
	//拼接TraceId
	engine.Use(traceId)
	//自定义日志打印
	engine.Use(preLog)
	engine.Use(afterLog)
	engine.Use(customRecovery)
	// 开启跨域
	engine.Use(cors)
	//404
	engine.NoRoute(func(c *gin.Context) {
		c.String(http.StatusNotFound, "404 not found")
	})
	return engine
}

// Cors 处理跨域请求
func cors(c *gin.Context) {
	method := c.Request.Method
	origin := c.Request.Header.Get("*.dra-m.com")
	c.Header("Access-Control-Allow-Origin", origin)
	c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id")
	c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT")
	c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
	c.Header("Access-Control-Allow-Credentials", "true")

	// 放行所有OPTIONS方法
	if method == "OPTIONS" {
		c.AbortWithStatus(http.StatusNoContent)
	}

	// 处理请求
	c.Next()
}
func preLog(c *gin.Context) {
	value, _ := c.Get("Trace")
	remoteIp := c.GetHeader("X-Real-IP")
	if remoteIp == "" {
		remoteIp = c.Request.RemoteAddr
	}

	global.Log.Infof("[%s] >>>>>>>>>>> [%s] %s From %s", value, c.Request.Method, c.Request.RequestURI, remoteIp)
	c.Next()
}
func afterLog(c *gin.Context) {
	defer func() {
		value, _ := c.Get("Trace")
		remoteIp := c.GetHeader("X-Real-IP")
		if remoteIp == "" {
			remoteIp = c.Request.RemoteAddr
		}
		global.Log.Infof("[%s] <<<<< [%3d] [%s] %s To %s", value, c.Writer.Status(), c.Request.Method, c.Request.RequestURI, remoteIp)
	}()
	c.Next()

}
func customRecovery(c *gin.Context) {
	defer func() {
		if err := recover(); err != nil {
			// Check for a broken connection, as it is not really a
			// condition that warrants a panic stack trace.
			var brokenPipe bool
			if ne, ok := err.(*net.OpError); ok {
				var se *os.SyscallError
				if errors.As(ne, &se) {
					if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
						brokenPipe = true
					}
				}
			}
			value, _ := c.Get("Trace")
			// 打印错误日志
			_, file, line, _ := runtime.Caller(2)
			for i := len(file) - 1; i > 0; i-- {
				if file[i] == '/' {
					file = file[i+1:]
					break
				}
			}
			g.Log.Errorf("[%s] %s (%s:%d)", value, err, file, line)

			if brokenPipe {
				// If the connection is dead, we can't write a status to it.
				c.Error(err.(error)) // nolint:
				c.Abort()
			} else {
				switch err.(type) {
				case string:
					response.ErrorWithInfo(err.(string)).Write(c)
					break
				case error:
					response.ErrorWithInfo(err.(error).Error()).Write(c)
					break
				default:
					response.ErrorWithInfo("发生不明错误").Write(c)
					break
				}

			}
		}
	}()
	c.Next()

}

func traceId(c *gin.Context) {
	trace := uuid.NewV4().String()
	c.Set("Trace", trace)
	c.Header("Trace", trace)
	c.Next()
}

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
105
106
107
108
109
110
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
136
137
138
139
140
141
142
143
144
145

#Golang#Gin#代码片段
上次更新: 10/23/2024
GitLab私服+Go Modules踩坑经验(SSH自定义端口)
【Java转Go】如何理解Go中的值类型、引用类型、nil

← GitLab私服+Go Modules踩坑经验(SSH自定义端口) 【Java转Go】如何理解Go中的值类型、引用类型、nil→

最近更新
01
mosquito配置ws协议
10-23
02
Pip包的离线下载和安装
10-23
03
stable diffusion 相关收藏
02-24
更多文章>
Theme by Vdoing | Copyright © 2019-2024 Dra-M
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式