golang后端开发之gin实例初始化配置

基于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()
    }
}

你可能感兴趣的:(golang后端开发之gin实例初始化配置)