REST API versioning in Go

Published: Oct 6, 2024
• • •

Making things deprecated

Things change, and therefore, API endpoints should sometimes become deprecated. This is something we need to add to our architecture.

I want to add two stages of "deprecated." The first stage is a warning that an endpoint is becoming deprecated. In this stage, the endpoint can still be used but adds a warning in the header. For this, we will set the "Deprecation" header to "true" and add an additional header field "Deprecation-Notes," which will contain information for the developers about what to do alternatively.

Deprecation: "true"
Deprecation-Notes: "v1 is deprecated, use /api/v2/something instead"

The next stage is the endpoint being removed. We still send the same headers, but now the status code will be 410 for "Gone" and the body will be just the string "API endpoint is deprecated".

// package handlers
func Deprecated(abort bool, notes string) gin.HandlerFunc {
	return func (c *gin.Context) {
		c.Header("Deprecation", "true")
		c.Header("Deprecation-Notes", notes)
		
		if abort {
			c.String(http.StatusGone, "api endpoint is deprecated")
			c.Abort()
		}
	}
}

// package main
func apiV1(r *gin.Engine) {
	v1 := r.Group("/api/v1")
	
	// This is a working endpoint
	v1.GET(
		"/something/current",
		handlers.GetSomething,
	)
	
	// This endpoint is deprecated but still works
	v1.GET(
		"/something/deprecated1",
		handlers.Deprecated(
			false, // Don't respond with 410 yet
			"This endpoint is deprecated, use /api/v1/something/current instead",
		),
		handlers.GetSomething,
	)
	
	// This endpoint is deprecated and stopped
	v1.GET(
		"/something/deprecated2",
		handlers.Deprecated(
			true, // This endpoint is not used anymore
			"This endpoint is deprecated, use /api/v1/something/current instead",
		),
	)
}