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
text/plain; charset=utf-8
I don't understand what I am missing, any idea ?
Doc :
func JSON
JSON serializes the given struct as JSON into the response body. It also sets the Content-Type as "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.
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...
EDIT 2
It seems like binding:"required"
break the 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.
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.
c.JSON
calls this function which calls the following code:
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.
Use c.ShouldBindJSON(&credentials)
instead of c.BindJSON
.
Gin README.md - Model binding and validation
These methods use MustBindWith under the hood. If there is a binding error, the request is aborted with c.AbortWithError(400, err).SetType(ErrorTypeBind). This sets the response status code to 400 and the Content-Type header is set to text/plain; charset=utf-8.
This can also happen if your output is not actually valid JSON and fails marshal. 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.