5

I have the following small program. It does not accept encoded double slashes (%2F%2F) even after using SkipClean while single encoded slash works fine.

Could someone please suggest what is going wrong here?

package main

import (
    "fmt"
    "net/http"
    "github.com/gorilla/mux"
)

func main() {
    r := mux.NewRouter().SkipClean(true).UseEncodedPath()
    r.HandleFunc("/", hiHandler)
    r.HandleFunc("/hi{*}", hiHandler).Methods("GET")
    http.Handle("/", r)
    http.ListenAndServe(":10801", nil)
}

func hiHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello world!")
}

#curl http://localhost:10801/hi%2Fds => this works

#curl http://localhost:10801/hi%2F%2Fds => this does not. Gives Moved Permanently error.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
mandeep
  • 433
  • 8
  • 17
  • 2
    The net/http server calls [path.Clean](https://godoc.org/path#Clean) on the decoded path. If the decoded path and the clean path are different, then the server redirects. I do not think there's a way to workaround this unfortunate design in the net/http server. The redirect is outside the control of the Gorilla. – Charlie Tumahai Aug 12 '20 at 06:06
  • @mandeep Try doing SkipClean(false). Look here: https://github.com/gorilla/mux/blob/master/mux.go#L173 – shmsr Aug 20 '20 at 18:40

1 Answers1

0

The trick is to run the server in a slightly different way.

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "log"
    "net/http"
    "time"
)

func main() {
    r := mux.NewRouter().SkipClean(true).UseEncodedPath()
    r.HandleFunc("/", hiHandler)
    r.HandleFunc("/hi{*}", hiHandler).Methods("GET")

    srv := &http.Server{
        Handler: r,
        Addr:    "localhost:10801",
        // Good practice: enforce timeouts for servers you create!
        WriteTimeout: 15 * time.Second,
        ReadTimeout:  15 * time.Second,
    }

    log.Fatal(srv.ListenAndServe())
}

func hiHandler(w http.ResponseWriter, r *http.Request) {
    // Putting the match of {*} into the output
    v := mux.Vars(r)
    fmt.Fprint(w, "Hello world! ", v["*"])
}

curl http://localhost:10801/hi%2Fds will output Hello world! %2Fds
curl http://localhost:10801/hi%2F%2Fds will output Hello world! %2F%2Fds.

tsak
  • 145
  • 1
  • 6