Dealing with Trailing Slashes on RequestURI in Go with Mux

23. March 2018 Blog 3

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:


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()
    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
        // 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…

3 thoughts on “Dealing with Trailing Slashes on RequestURI in Go with Mux”

  • 1
    Gavin on May 15, 2018 Reply

    You just saved me a lot of headache. Thanks!

  • 2
    Frederik Vosberg on July 24, 2018 Reply

    Hi, thanks for this thoughts. The solution is good and it saves others from having to go the same learning path, as you did. One thing I would like to mention: If you just read the main function, you won’t expect something like a loggingMiddleware to change anything. So I suggest to have two middlewares like

    http.ListenAndServe(port, loggingMiddleware(trailingSlashesMiddleware(router)))

    So if anything goes wrong according to routing, you know you might want to have a look at this middleware, in particular when you define a Route with a trailing slash, which would never match.

    • 3
      pitchinnate on August 15, 2018 Reply

      Correct I agree, I did end up making it into it’s own middleware. Thanks for your feedback.

Leave a Reply

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