Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CleanPath middleware does not work correctly with http CONNECT requests #807

Open
samiponkanenssh opened this issue Mar 27, 2023 · 2 comments

Comments

@samiponkanenssh
Copy link

If the same router handles REST API requests and http CONNECT requests, then it is not possible to use middleware.CleanPath. CleanPath will mess up ctx.RoutePath for typical http CONNECT URIs, which are of the format host:port. This causes go-chi to respond to CONNECT requests with 404 Not Found.

I need to use to a workaround like below to get it working. Fixing middleware.CleanPath to not do anything for CONNECT requests would be the correct fix.

package main

import (
        "log"
        "net/http"
        "net/http/httputil"

        "github.com/go-chi/chi/v5"
        "github.com/go-chi/chi/v5/middleware"
)

func main() {
        mux := chi.NewRouter()
        mux.Use(middleware.CleanPath)
        mux.Use(httpConnectMiddleWare)
        mux.Method("GET", "/", http.HandlerFunc(ServeDefault))
        mux.Method("CONNECT", "/*", http.HandlerFunc(ServeConnect))

        http.ListenAndServe("127.0.0.1:8080", mux)
}

func httpConnectMiddleWare(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                ctx := chi.RouteContext(r.Context())
                if r.Method == http.MethodConnect {
                        ctx.RoutePath = "/"
                }
                next.ServeHTTP(w, r)
        })
}

func ServeDefault(w http.ResponseWriter, r *http.Request) {
        dump, _ := httputil.DumpRequest(r, false)
        log.Printf("%s", string(dump))
}

func ServeConnect(w http.ResponseWriter, r *http.Request) {
        dump, _ := httputil.DumpRequest(r, false)
        log.Printf("%s", string(dump))
}
@kubosuke
Copy link

@samiponkanenssh
Hi, I ran your script and test with provided format host:port, but seems it returns the expected response, not 404.
will you share the request for reproducing 404?

❯ curl localhost:8080/t/e///s/t/// -X CONNECT -I
HTTP/1.1 200 OK
Date: Sat, 20 May 2023 05:38:23 GMT
Content-Length: 0


❯ curl localhost:8080/t/e///s/t/// -X GET -I
HTTP/1.1 405 Method Not Allowed
Date: Sat, 20 May 2023 05:38:28 GMT
Content-Length: 0


❯ curl localhost:8080/ -X GET -I
HTTP/1.1 200 OK
Date: Sat, 20 May 2023 05:38:32 GMT
Content-Length: 0

@samiponkanenssh
Copy link
Author

@kubosuke

Hi,

Sorry for the late response.

Your curl command will not produce a valid HTTP CONNECT request:

 curl -v localhost:8080/t/e///s/t/// -X CONNECT -I
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> CONNECT /t/e///s/t/// HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Date: Tue, 06 Jun 2023 13:53:04 GMT
Date: Tue, 06 Jun 2023 13:53:04 GMT
< Content-Length: 0
Content-Length: 0

< 
* Connection #0 to host localhost left intact

However if you use netcat, you will see this error without the workaround:

$ nc -v -X connect -x localhost:8080 google.com 443
nc: Proxy error: "HTTP/1.0 404 Not Found"

With the workaround you will see this:

$ nc -v -X connect -x localhost:8080 google.com 443
Connection to google.com 443 port [tcp/https] succeeded!
^C

Br,
Sami

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants