Dealing with Trailing Slashes on RequestURI in Go with Mux

23. March 2018 Blog 0

I recently was building a REST API with Go and I utilized gorilla/mux for routing. I quickly realized that if you create a router handler it doesn’t handle trailing slashes. So if you write code like this:

router.HandleFunc("/users",GetList).Methods("GET")

It would get would handle requests to /users but not /users/. So I did a little bit of research and sure enough Mux has an option to handle this called StrictSlashes. If you enable this feature then it redirects routes without a trailing slash to a route with a trailing slash, it did exactly what I needed. That is until I got to a POST request. If you read the documentation for ScrictSlashes it lets you know that it generates a 301 redirect and converts all requests to GET requests. So my POST to /users was turning into a GET to /users/.

So I figured I would try to write some middleware for Mux that would handle this. However, middleware for Mux doesn’t fire till after it finds the handler for the route, so once again no go. Finally, I tried writing a http Handler outside of Mux. This is what I ended up with and it works great.

func main() {
    router := mux.NewRouter()
    router.HandleFunc("/users",GetList).Methods("GET")
    router.HandleFunc("/users",PostInsert).Methods("POST")
    log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d",port), loggingMiddleware(router)))
}

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        r.URL.Path = strings.TrimSuffix(r.URL.Path, "/")
        // Do stuff here
        log.Println(r.RequestURI)
        // Call the next handler, which can be another middleware in the chain, or the final handler.
        next.ServeHTTP(w, r)
    })
}

On my first attempt I tried just modifying r.RequestURI however, I figured out Mux actually uses r.URL.PATH when matching routes. So all this function does is trims off any trailing slashes. So now you just need a router handler for /users and it will handle requests to /users/ and it works for any type of requests GET, POST, PUT, etc…


Leave a Reply

Your email address will not be published. Required fields are marked *