简体   繁体   English

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

[英]golang gin gonic content-type not setting to application/json with c.JSON

According to the official documentation , c.JSON of gin-gonic should set the response header to application/json , but when I call my API from Postman , the response header is set to text/plain; charset=utf-8根据官方文档gin-gonic 的 c.JSON应该将响应头设置为application/json ,但是当我从Postman调用我的 API 时,响应头设置为text/plain; charset=utf-8 text/plain; charset=utf-8

I don't understand what I am missing, any idea ?我不明白我错过了什么,有什么想法吗?

Doc :文件:

func JSON函数 JSON

JSON serializes the given struct as JSON into the response body. JSON 将给定的结构作为 JSON 序列化到响应正文中。 It also sets the Content-Type as "application/json".它还将 Content-Type 设置为“application/json”。

Here is a sample of my code :这是我的代码示例:

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)
    }
}

EDIT编辑

After investigation, log.Println(c.Writer.Header().Get("Content-Type")) doesn't print any thing, showing content-type is empty as it should be.经过调查, 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
    }
}

I really don't want to have to add c.Writer.Header().Set("Content-Type", "application/json") to every route in my architecture...我真的不想将c.Writer.Header().Set("Content-Type", "application/json")添加到我架构中的每条路由中......

EDIT 2编辑 2

It seems like binding:"required" break the Content-Type Header似乎binding:"required"打破了 Content-Type Header

type Credentials struct {
    Email         string        `json:"email" binding:"required"`
    Password      string        `json:"password" binding:"required"`
}

If you expect all your requests to be JSON, add a middle ware instead.如果您希望所有请求都是 JSON,请添加一个中间件。

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

On your router add在您的路由器上添加

router.Use(JSONMiddleware())

After looking at the source, it looks like it won't write the Content-Type header if it is already set.看了下源码,好像已经设置了Content-Type头就不会写了。

c.JSON calls this function which calls the following code: c.JSON调用此函数,该函数调用以下代码:

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

Therefore your Content-Type must be set somewhere else.因此,您的Content-Type必须设置在其他地方。

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

Gin README.md - Model binding and validation Gin README.md - 模型绑定和验证

These methods use MustBindWith under the hood.这些方法在后台使用 MustBindWith。 If there is a binding error, the request is aborted with c.AbortWithError(400, err).SetType(ErrorTypeBind).如果存在绑定错误,则使用 c.AbortWithError(400, err).SetType(ErrorTypeBind) 中止请求。 This sets the response status code to 400 and the Content-Type header is set to text/plain;这会将响应状态代码设置为 400,并将 Content-Type 标头设置为 text/plain; charset=utf-8.字符集=utf-8。

This can also happen if your output is not actually valid JSON and fails marshal.如果您的输出实际上不是有效的 JSON 并且封送失败,也会发生这种情况。 I saw content-type being set to application/text when i was not returning in an error handler, and i was accidentally concatenating a string onto JSON as a result of my poor error handling.当我没有在错误处理程序中返回时,我看到内容类型被设置为应用程序/文本,并且由于我的错误处理不当,我不小心将一个字符串连接到 JSON 上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM