为了账号安全,请及时绑定邮箱和手机立即绑定

当服务器使用 gin-gonic 和 gin-contrib/gzip 发生恐慌时

当服务器使用 gin-gonic 和 gin-contrib/gzip 发生恐慌时

Go
胡说叔叔 2022-07-04 16:26:50
当访问gin-gonic下面的服务器时,HTTP 客户端应该收到代码 500,但收到的代码是 200。package mainimport (    "github.com/gin-contrib/gzip"    "github.com/gin-gonic/gin")func main() {    gin.SetMode(gin.ReleaseMode)    r := gin.New()    r.Use(gin.Logger())    r.Use(gin.Recovery())    r.Use(gzip.Gzip(gzip.DefaultCompression))    r.POST("/test", func(c *gin.Context) {        panic("test")                        // Server panic and client should receive code 500.    })    r.Run(":8080")}从 HTTP 客户端访问/test时,go server 日志如下所示,看起来返回代码 500。[GIN] 2020/09/28 - 10:23:14 | 500 |     67.2995ms |             ::1 | POST     "/test"2020/09/28 10:23:14 [Recovery] 2020/09/28 - 10:23:14 panic recovered:testC:/path/to/myproject/main.go:16 (0x8f193f)    main.func1: panic("test")但是 HTTP 客户端收到代码 200。当我删除r.Use(gzip.Gzip(gzip.DefaultCompression))时,HTTP 客户端会收到代码 500。为什么客户收到代码 200 r.Use(gzip.Gzip(gzip.DefaultCompression)),我该如何解决?
查看完整描述

2 回答

?
慕标琳琳

TA贡献1830条经验 获得超9个赞

我已经复制了你的情况。邮递员得到代码 200,但服务器结果却是 500。


服务器在收到 post 请求时会调用 c.Next() 来执行 4 个处理程序。顺序如下:


gin.Logger

gin.Recovery

gzip.Gzip(gzip.DefaultCompression)

your handler

这是 gin responseWriter 写入响应头,它只会写入一次头。


func (w *responseWriter) WriteHeaderNow() {

    if !w.Written() {

        w.size = 0

        w.ResponseWriter.WriteHeader(w.status)

    }

}

两者都gzip.Gzip(gzip.DefaultCompression)具有gin.Recovery延迟函数来写入响应标头。Golang 的延迟调用按后进先出的顺序执行。所以gzip.Gzip(gzip.DefaultCompression)会将响应头写入 200,并且gin.Recovery不会按预期将响应头写入 500。


所以要解决这个问题,你应该改变处理程序的顺序,并确保gin.Recovery是最后加载的处理程序。


查看完整回答
反对 回复 2022-07-04
?
杨魅力

TA贡献1811条经验 获得超6个赞

最后添加恢复中间件似乎可以解决这个问题。


package main


import (

    "github.com/gin-contrib/gzip"

    "github.com/gin-gonic/gin"

)


func main() {

    gin.SetMode(gin.ReleaseMode)

    r := gin.New()

    r.Use(gin.Logger())

    r.Use(gzip.Gzip(gzip.DefaultCompression))

    r.Use(gin.Recovery())


    r.POST("/test", func(c *gin.Context) {

        panic("test")                        // Server panic and client should receive code 500.

    })


    r.Run(":8080")

}


查看完整回答
反对 回复 2022-07-04
  • 2 回答
  • 0 关注
  • 189 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信