julienschmidt / httprouter

A high performance HTTP request router that scales well
https://pkg.go.dev/github.com/julienschmidt/httprouter
BSD 3-Clause "New" or "Revised" License
16.64k stars 1.47k forks source link

not handling escaped forward slashes properly #208

Open tmornini opened 7 years ago

tmornini commented 7 years ago

Hey there. Just found this issue:

package main

import (
    "net/http"

    "github.com/julienschmidt/httprouter"
)

func main() {
    router := httprouter.New()

    router.GET(
        "/networks/:network-id/accounts/:network-account-id/purchases/:purchase-id",
        getPurchaseHTTPRouter,
    )

    panic(http.ListenAndServe(":8080", router))
}

func getPurchaseHTTPRouter(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
    w.WriteHeader(200)
    w.Write([]byte("routed\n"))
}

Without an encoded forward slash, this works correctly:

$ curl localhost:8080/networks/1/accounts/2/purchases/3
routed

But with an encoded forward slash, it does not.

$ curl localhost:8080/networks/1/accounts/2/purchases/3%2F4
404 page not found

I'm quite confident that the second example should have routed and the purchase-id parameters should be set to "3/4"

RazerM commented 5 years ago

ORY Hydra had an API where you accept a parameter like /login?login_challenge={challenge}, and then you call Hydra's API with /oauth2/auth/requests/login/{challenge}. They recently changed to use query parameters so the API caller doesn't have to escape the challenge (ory/hydra#1307).

The linked issue says "if [the] challenge is not properly escaped", but that's not true because it uses httprouter! Calling /oauth2/auth/requests/login/..%2F..%2F..%2F..%2Fclients (which is properly escaped) would change the Hydra request path.

I don't use httprouter directly, but when Hydra announced the change and I checked that even with escaping it doesn't work I was quite surprised.

RFC 3986: "When to Encode or Decode":

When a URI is dereferenced, the components and subcomponents significant to the scheme-specific dereferencing process (if any) must be parsed and separated before the percent-encoded octets within those components can be safely decoded, as otherwise the data may be mistaken for component delimiters.