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

net/http: cannot register ServeMux handler for all CONNECT requests regardless of host or path #9561

Closed
kr opened this issue Jan 11, 2015 · 7 comments

Comments

@kr
Copy link
Contributor

kr commented Jan 11, 2015

Go version 1.4 and head (4e03bbb), all platforms.

It doesn't appear to be possible to register a ServeMux handler that works for all CONNECT requests, regardless of hostname or path.

Steps to reproduce
  1. Register a ServeMux handler for "/". http://play.golang.org/p/iIU0eJ3Idn

  2. Send a proxy request:

    CONNECT example.com:443 HTTP/1.1
    
Expected behavior

The program prints something like

handle CONNECT "example.com:443" ""

and returns a 200 response.

Observed behavior

The program prints nothing and returns 404.

Notes

As http.ServeMux.handler notes, its path parameter is in canonical form, except for CONNECT requests. In this case the path is the empty string, so it never matches against a ServeMux entry that has a non-empty path.

It is possible to register a ServeMux handler for a particular host, as in

http.Handle("example.com:443", foo)

and this receives CONNECT requests as expected. But it doesn't appear to be possible to register a handler as a generic fallback for CONNECT requests, as one might hope to do with "/". (And ServeMux explicitly rejects the empty string as an invalid pattern.)

A possible workaround is "don't use ServeMux for this", but perhaps there is a fix.

ServeMux.Handler might fix this by explicitly using "/" as the path argument to ServeMux.handler for a CONNECT request with an empty path. E.g.:

func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
    path := r.URL.Path
    if r.Method != "CONNECT" {
        if p := cleanPath(r.URL.Path); p != r.URL.Path {
            _, pattern = mux.handler(r.Host, p)
            url := *r.URL
            url.Path = p
            return RedirectHandler(url.String(), StatusMovedPermanently), pattern
        }
    } else if path == "" {
        path = "/"
    }

    return mux.handler(r.Host, path)
}

I'm not sure if that's a reasonable approach.

@rsc
Copy link
Contributor

rsc commented Apr 10, 2015

This has come up before. We would need to figure out the syntax for this.

@rsc rsc added this to the Go1.5Maybe milestone Apr 10, 2015
@rsc rsc removed the repo-main label Apr 14, 2015
@rsc
Copy link
Contributor

rsc commented Jun 29, 2015

We didn't manage to get to this for Go 1.5. I apologize for that, but it does seem that there is an easy workaround: register a handler in front of the servemux that picks off CONNECT requests.

@rsc rsc modified the milestones: Go1.6Early, Go1.5Maybe Jun 29, 2015
@bradfitz
Copy link
Contributor

bradfitz commented Dec 1, 2015

I don't think ServeMux needs to do everything. It's very easy to write your own mux, and CONNECT is a pretty advanced case. Anybody needing CONNECT (like @kr) knows how to write their own.

In the interest of minimizing changes in the standard library, I'm going to close this. Feel free to argue if you feel strongly.

@bradfitz bradfitz closed this as completed Dec 1, 2015
@kr
Copy link
Contributor Author

kr commented Dec 2, 2015

Sounds good to me. I don't feel strongly about it, just wanted to bring it up.

@fanyang01
Copy link

There is no way to register a proxy handler in App Engine due to this issue. In a normal environment, it can be avoided by using http.ListenAndServe. However for App Engine environment, only http.Handle is available.

@davecheney
Copy link
Contributor

@fanyang01 please don't discussions on closed issues. Please see https://golang.org/wiki/Questions for good places to ask. Thanks.

@fanyang01
Copy link

Sorry. I will open a new issue for this.

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

No branches or pull requests

7 participants