Routing

Till now we used routing directly inside of our handlers. For a large application though, it'd be better to have a router in place. We can either use a third party one with countless features or the standard mux.

As our application matures, routing plays a big role into it. We intentionally avoided routing till now because as a web developer, we must understand what happens in the background of our application. Web frameworks allow us to build applications quickly, but the downside of them is that they provide us with a framework as the name suggests, which means you are totally restricted by the API which the framework will provide. Thus we need to know how to implement bare bone stuff, so in future we might want to modify the framework we need, or rather create our own one.

First of all we'd need to install the httprouter, do a go get -u github.com/julienschmidt/httprouter

From the documentation

Package httprouter is a trie based high performance HTTP request router.

package main

import (
    "fmt"
    "github.com/julienschmidt/httprouter"
    "net/http"
    "log"
)

func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    fmt.Fprint(w, "Welcome!\n")
}

func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
    fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
}

func main() {
    router := httprouter.New()  // creates a new router
    router.GET("/", Index)      // will direct the GET / request to the Index function
    router.GET("/hello/:name", Hello) // will redirect the GET /name to Hello, stores the name of the parameter
                                        // in the a variable of httprouter.Params  

    log.Fatal(http.ListenAndServe(":8080", router))
}

httprouter uses a custom Http.HandleFunc method to accomodate parameterized routing.

Here, we can route our requests depending on the HTTP method through which it is used, and we can handle parameterized routing for free.

To handle that scenario we were initially using the r.URL.Path variable and then extracting the parameters, it is just the solution of finding the variable parameter of the URL, there is a wide area where httprouter is awesome, there is no need to handle the / for each requests.

In web applications sometimes having a forward slash is very critical, the URL index is totally different from /index and is marginally different from /index/ httprouter takes care of the trailing slashes. The Go default MUX requires you to handle the routes in the descending order, meaning the most generic URL the "/" should be at the bottom and the least generic should be at the top, as it goes sequentially up and down matching the URLs, httprouter provides a wide variety of advantages when it comes to routing.

This is because our application should separate routing from the handler logic, we were mixing it just to get a feel for how to program in Go, but eventually when the app grows, it is tiresome and non maintainable for doing the if r.Method==POST check in each handler, rather than that we can have 3 different handlers one for when request comes via AJAX, one for normal GET and one for normal POST. This way we do not have one function handler checking the type of request and then writing three separate logic inside one function.

But that doesn't mean we have to use httprouter, if in an app there aren't much sophisticated routing required then we can use the default Mux since it is good enough, but if we have complicated routing then httprouter is the best.

Homework

Read the httprouter documentation and source code to get a deeper understanding of routers, since routers are an integral part of any web application. Then rewrite our application using the httprouter.

-Previous section -Next section

Last updated