Wednesday, 15 April, 2020 UTC


Summary

If you're just getting your hands dirty with Golang, and specifically with Gin, which is a web development framework, you might come across this specific warning:
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 200
Most likely, you're trying to use BindJSON on a property that does not exist.
Here's an example.
I'm building an analytics solution for weremote.eu and for its pageview counter, I wanted to also be able to pass in extra props besides the usual props such an event would carry.
r.GET("/record/:pageID/0.gif", func(c *gin.Context) { pageID := c.Params.ByName("pageID") trackingID := createTrackingID(c.ClientIP()) var extras map[string]interface{} // the problem was this line here err := c.BindJSON(&extras) if err != nil { log.Println("No extras provided") } e := event.Event{ TrackingID: trackingID, Type: event.PageView, CreatedAt: time.Now(), PageID: pageID, Extras: extras, } producer.PageView(e) c.Header("Content-Type", "image/gif") c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat)) c.Header("Expires", "Wed, 11 Nov 1998 11:11:11 GMT") c.Header("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0") c.Header("Pragma", "no-cache") c.Data(http.StatusOK, "application/octet-stream", pixel) return })
As you can see from the code, the problem is with context.BindJSON because it is a shortcut for context.MustBindWith(obj, binding.JSON). The keyword here is Must. This means that if my pageview event would not get any extras that code would fail.
And it triggers the warning you saw in the title.
While looking through the docs I found the solution. It's ShouldBindJSON which is more lax when you pass empty maps to it 😅
So I just made that line of code look like this : err := c.ShouldBindJSON(&extras) and it solved the whole problem.
That's it! Happy Go-ing!