Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the idiomatic way to handle api versions [closed]

I'm creating a server in Go intended for a mobile app. I need to be able to support multiple versions of the API for cases were users don't update the app. The main concern with the versioning, is to return data in the correct format for the version of the mobile app.

I've seen that there are three basic ways to do this.
A. One way is by having one route handler on "/", and then allowing that function to parse the url for versioning.
Example:

func main() {
http.HandleFunc("/", routes.ParseFullURI)
}

B. Use a library such as gorilla/mux to handle patterns within the router, but I saw some warnings that this can be too slow.
Example:

  func main() {
            mux.HandleFunc("{version:}/", routes.ParseVersionForHome)
            mux.HandleFunc("{version:}/getData", routes.ParseVersionForGetDAta)
            mux.HandleFunc("{version:}/otherCall", routes.ParseVersionForOtherCall)
            }

C. Have individual urls that don't change, but based on the header, split into different versions. Example:

func main() {
   http.HandleFunc("/", routes.ParseHeaderForVersionForHome)
   http.HandleFunc("/getData", routes.ParseHeaderForVersionForGetData)
   http.HandleFunc("/otherCall", routes.ParseHeaderForVersionForOtherCall)
}

I'm concerned that option 1 will be too messy code wise. I'm concerned that option 2 will be too slow performance wise, and I'm concerned that option 3 will be difficult for the client to handle, or will get confusing since the version isn't clearly labeled.

Which method is the most idiomatic for Go, and will result in the greatest performance for a mobile app which will be polling often?

like image 770
Avik Avatar asked Apr 21 '15 17:04

Avik


1 Answers

There are many routing frameworks that allow for grouping, for instance with echo (a very good framework if you want speed)

package main

import "github.com/labstack/echo"

func ping(c *echo.Context) {
        c.String(200, "pong")
}

func main() {
        e := echo.New()

        v1 := e.Group("/v1")
        v1.Get("/ping", ping)

        v2 := e.Group("/v2")
        v2.Get("/ping", ping)

        e.Run(":4444")
}

I think this is quite clean.

I am sure many other frameworks allow for this. I know for a fact martini does, but that is not an idiomatic framework...

like image 154
placeybordeaux Avatar answered Oct 26 '22 23:10

placeybordeaux