gin
gin copied to clipboard
JSON inf value sends 200 response but error in server logs
Description
When using JSON response gin fails to send error response in case json.Marshal fails to encode data and sends 200 response code along with empty response. So the app doesn't know error happened and no context/error code provided.
This is a commonly issue when you have a data from a nullable float fields of database. This is possible when some of your data is NaN, or Inf+/-.
How to reproduce
package main
import (
"math"
"github.com/gin-gonic/gin"
)
func main() {
g := gin.Default()
g.GET("/test", func(c *gin.Context) {
c.JSON(200, gin.H{
"inf_value": math.Inf(1),
})
})
g.Run(":9000")
}
Expectations
$ curl http://localhost:9000/test
HTTP/1.1 500
Actual result
$ curl -i http://localhost:9000/test
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Mon, 02 Oct 2023 16:57:13 GMT
Content-Length: 0
Environment
- go version: 1.20.8
- gin version (or commit ref): latest
The error is attached to the context since the response rendering end up with an error.
https://github.com/gin-gonic/gin/blob/4ea0e648e38a63d6caff14100f5eab5c50912bcd/context.go#L928
My view is maybe adding a error handling middleware will be better than just have its behavior fixed whenever the response rendering come up with errors. Further more, have this behavior changed may introduce a break change to people who depends on it.
Example of @tarupo 's recommendation:
package middleware
import (
"github.com/gin-gonic/gin"
"github.com/whiskaway/whiskaway-api/api/responses"
)
func CatchAllMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
if len(c.Errors) > 0 && c.Writer.Status() == 200 {
c.JSON(500, responses.InternalServerErrorValue)
}
}
}
router := gin.New()
router.Use(middleware.CatchAllMiddleware())