golang gin gonic 内容类型未使用 c.JSON 设置为 application/json

Adr*_*ien 5 json go

根据官方文档gin-gonic的 c.JSON应该将响应头设置为application/json,但是当我从Postman调用我的 API 时,响应头设置为text/plain; charset=utf-8

我不明白我错过了什么,有什么想法吗?

文件:

函数 JSON

JSON 将给定结构序列化为 JSON 到响应正文中。它还将 Content-Type 设置为“application/json”。

这是我的代码示例:

func postLogin(c *gin.Context) {
    var credentials DTO.Credentials
    if err := c.BindJSON(&credentials); err == nil {
        c.JSON(buildResponse(services.CheckUserCredentials(credentials)))
    } else {
        var apiErrors = DTO.ApiErrors{}
        for _, v := range err.(validator.ValidationErrors) {
            apiErrors.Errors = append(apiErrors.Errors, DTO.ApiError{Field: v.Field, Message: v.Field + " is " + v.Tag})
        }
        c.JSON(http.StatusBadRequest, apiErrors)
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

经过调查, log.Println(c.Writer.Header().Get("Content-Type")) 不打印任何内容,显示 content-type 应该是空的。

func writeContentType(w http.ResponseWriter, value []string) {
    header := w.Header()
    log.Println(header.Get("Content-Type")) // <=========== Nothing happen
    if val := header["Content-Type"]; len(val) == 0 {
        header["Content-Type"] = value
    }
}
Run Code Online (Sandbox Code Playgroud)

我真的不想添加c.Writer.Header().Set("Content-Type", "application/json")到我的架构中的每条路线......

编辑2

似乎binding:"required"破坏了 Content-Type 标头

type Credentials struct {
    Email         string        `json:"email" binding:"required"`
    Password      string        `json:"password" binding:"required"`
}
Run Code Online (Sandbox Code Playgroud)

小智 11

使用c.ShouldBindJSON(&credentials)而不是c.BindJSON.

Gin README.md - 模型绑定和验证

这些方法在底层使用 MustBindWith。如果存在绑定错误,则使用 c.AbortWithError(400, err).SetType(ErrorTypeBind) 中止请求。这会将响应状态代码设置为 400,并将 Content-Type 标头设置为 text/plain;字符集=utf-8。

正如Eutychus在评论中所说:在幕后c.BindJSON使用。MustBindWith如果存在绑定错误,则请求将中止,响应状态代码将设置为 400,Content-Type标头将设置为text/plain; charset=utf-8

引擎盖下的ShouldBindJSON用途。ShouldBindWith如果存在绑定错误,则会返回错误,并且开发人员有责任适当处理请求和错误。这就是为什么在这种情况下它是更好的。


Bil*_*try 8

如果您希望所有请求都是 JSON,请添加中间件。

func JSONMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Writer.Header().Set("Content-Type", "application/json")
        c.Next()
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的路由器上添加

router.Use(JSONMiddleware())
Run Code Online (Sandbox Code Playgroud)


squ*_*guy 4

查看源代码后,看起来Content-Type如果已经设置了标头,则不会写入标头。

c.JSON调用此函数,该函数调用以下代码:

func writeContentType(w http.ResponseWriter, value []string) {
    header := w.Header()
    if val := header["Content-Type"]; len(val) == 0 {
        header["Content-Type"] = value
    }
}
Run Code Online (Sandbox Code Playgroud)

因此你Content-Type必须设置在其他地方。