基于ferry项目学习总结
代码地址:https://gitee.com/yllan/ferry
r := gin.New()
request,response后端服务常规配置
r.Use(LoggerToFile()) 记录请求日志(starttime,latencytime,cip, requestMethod, Uri)
func LoggerToFile() gin.HandlerFunc {
return func(c *gin.Context) {
// 开始时间
startTime := time.Now()
// 处理请求
c.Next()
// 结束时间
endTime := time.Now()
// 执行时间
latencyTime := endTime.Sub(startTime)
// 请求方式
reqMethod := c.Request.Method
// 请求路由
reqUri := c.Request.RequestURI
// 状态码
statusCode := c.Writer.Status()
// 请求IP
clientIP := c.ClientIP()
// 日志格式
logger.Infof(" %s %3d %13v %15s %s %s",
startTime.Format("2006-01-02 15:04:05.9999"),
statusCode,
latencyTime,
clientIP,
reqMethod,
reqUri,
)
}
}
r.Use(CustomError) 自定义错误处理
func CustomError(c *gin.Context) {
defer func() {
//如当前context被终止返回true
if err := recover(); err != nil {
if c.IsAborted() {
c.Status(200)
}
switch errStr := err.(type) {
case string:
p := strings.Split(errStr, "#")
if len(p) == 3 && p[0] == "CustomError" {
statusCode, e := strconv.Atoi(p[1])
if e != nil {
break
}
c.Status(statusCode)
fmt.Println(
time.Now().Format("\n 2006-01-02 15:04:05.9999"),
"[ERROR]",
c.Request.Method,
c.Request.URL,
statusCode,
c.Request.RequestURI,
c.ClientIP(),
p[2],
)
c.JSON(http.StatusOK, gin.H{
"code": statusCode,
"msg": p[2],
})
}
default:
panic(err)
}
}
}()
c.Next()
}
r.Use(NoCache) 设置no-cache
func NoCache(c *gin.Context) {
c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value")
c.Header("Expires", "Thu, 01 Jan 1970 00:00:00 GMT")
c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
c.Next()
}
r.Use(Options) 支持跨域请求
func Options(c *gin.Context) {
if c.Request.Method != "OPTIONS" {
c.Next()
} else {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS")
c.Header("Access-Control-Allow-Headers", "authorization, origin, content-type, accept")
c.Header("Allow", "HEAD,GET,POST,PUT,PATCH,DELETE,OPTIONS")
c.Header("Content-Type", "application/json")
c.AbortWithStatus(200)
}
}
r.Use(Secure) 设置Header安全策略
func Secure(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
//c.Header("X-Frame-Options", "DENY")
c.Header("X-Content-Type-Options", "nosniff")
c.Header("X-XSS-Protection", "1; mode=block")
if c.Request.TLS != nil {
c.Header("Strict-Transport-Security", "max-age=31536000")
}
// Also consider adding Content-Security-Policy headers
// c.Header("Content-Security-Policy", "script-src 'self' https://cdnjs.cloudflare.com")
}
r.Use(RequestId()) 设置X-Request-Id,主要用于日志分析
func RequestId() gin.HandlerFunc {
return func(c *gin.Context) {
// Check for incoming header, use it if exists
requestId := c.Request.Header.Get("X-Request-Id")
// Create request id with UUID4
if requestId == "" {
u4 := uuid.NewV4()
requestId = u4.String()
}
// Expose it for use in the application
c.Set("X-Request-Id", requestId)
c.Writer.Header().Set("X-Request-Id", requestId)
c.Next()
}
}