Oprea.Rocks Logo

Get updates on new articles, and other opportunities

Fixing Golang: [GIN-debug] [WARNING] Headers were already written.

Screenshot 2020-02-16 at 10.44.43 PM

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.

Gin Golang BindJSON

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 😅

Gin Golang ShouldBindJSON

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!