When adding different handlers to a Router, each one with its own base path (sub routing), it comes handy to list all the endpoints declared, not only as a debug option but also when you want your API to expose all the methods it’s support.
Gorilla Mux
My favourite web toolkit in Go is the Gorilla Web Toolkit, which apart of the router and dispatcher Gorilla Mux, has also other packages for handling cookies in a secure way, using web sockets, and even RPC over HTTP.
If the following example you will see a common pattern I use when building services using Gorilla Mux. I start by creating a service layer (in this case then bots are my services), and the an API layer that defines endpoints and calls the service (controller). So imagine have two separate controllers and services, or more, each one with its own path.
func main() {
fmt.Println("Starting messaging bot")
//Create our Gorilla mux main router which path is "/api"
mainRouter := mux.NewRouter().
PathPrefix("/api").
Subrouter().
StrictSlash(true)
//Create WhatsApp bot
whatsAppBot := bots.NewWhatsAppBot()
//Create a sub router at "/api/whatsapp"
api.NewAPI(whatsAppBot,
mainRouter.PathPrefix("/whatsapp").
Subrouter().
StrictSlash(true))
//Create Telegram bot and API server
telegramBot := bots.NewTelegramBot()
//Create a sub router at "/api/telegram"
api.NewAPI(telegramBot,
mainRouter.PathPrefix("/telegram").
Subrouter().
StrictSlash(true))
fmt.Println("WhatsApp bot running on /api/whatsapp")
fmt.Println("Telegram bot running on /api/telegram")
//Start the HTTP server on port 8000
http.ListenAndServe(":8000", mainRouter)
}
Every Router has a Walk function that let’s us navigate all the endpoints we define. If we want to debug which endpoint has been declared in our main router, we can call a function like the one below:
func printEndpoints(r *mux.Router) {
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
path, err := route.GetPathTemplate()
if err != nil {
return nil
}
methods, err := route.GetMethods()
if err != nil {
return nil
}
fmt.Printf("%v %s\n", methods, path)
return nil
})
}
In my example this function will print
Starting messaging bot
[GET] /api/whatsapp/login
[POST] /api/whatsapp/message
[GET] /api/telegram/login
[POST] /api/telegram/message
Listening on port 8000