Commit f1e88038 authored by Kenny Grant's avatar Kenny Grant Committed by Brad Fitzpatrick

net/http: strip port from host in mux Handler

This change strips the port in mux.Handler before attempting to
match handlers and adds a test for a request with port.

CONNECT requests continue to use the original path and port.

Fixes #10463

Change-Id: Iff3a2ca2b7f1d884eca05a7262ad6b7dffbcc30f
Reviewed-on: https://go-review.googlesource.com/38194Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 369d1083
...@@ -337,6 +337,7 @@ var serveMuxTests = []struct { ...@@ -337,6 +337,7 @@ var serveMuxTests = []struct {
{"GET", "codesearch.google.com", "/search/", 203, "codesearch.google.com/"}, {"GET", "codesearch.google.com", "/search/", 203, "codesearch.google.com/"},
{"GET", "codesearch.google.com", "/search/foo", 203, "codesearch.google.com/"}, {"GET", "codesearch.google.com", "/search/foo", 203, "codesearch.google.com/"},
{"GET", "codesearch.google.com", "/", 203, "codesearch.google.com/"}, {"GET", "codesearch.google.com", "/", 203, "codesearch.google.com/"},
{"GET", "codesearch.google.com:443", "/", 203, "codesearch.google.com/"},
{"GET", "images.google.com", "/search", 201, "/search"}, {"GET", "images.google.com", "/search", 201, "/search"},
{"GET", "images.google.com", "/search/", 404, ""}, {"GET", "images.google.com", "/search/", 404, ""},
{"GET", "images.google.com", "/search/foo", 404, ""}, {"GET", "images.google.com", "/search/foo", 404, ""},
......
...@@ -2167,6 +2167,19 @@ func cleanPath(p string) string { ...@@ -2167,6 +2167,19 @@ func cleanPath(p string) string {
return np return np
} }
// stripHostPort returns h without any trailing ":<port>".
func stripHostPort(h string) string {
// If no port on host, return unchanged
if strings.IndexByte(h, ':') == -1 {
return h
}
host, _, err := net.SplitHostPort(h)
if err != nil {
return h // on error, return unchanged
}
return host
}
// Find a handler on a handler map given a path string. // Find a handler on a handler map given a path string.
// Most-specific (longest) pattern wins. // Most-specific (longest) pattern wins.
func (mux *ServeMux) match(path string) (h Handler, pattern string) { func (mux *ServeMux) match(path string) (h Handler, pattern string) {
...@@ -2195,7 +2208,10 @@ func (mux *ServeMux) match(path string) (h Handler, pattern string) { ...@@ -2195,7 +2208,10 @@ func (mux *ServeMux) match(path string) (h Handler, pattern string) {
// consulting r.Method, r.Host, and r.URL.Path. It always returns // consulting r.Method, r.Host, and r.URL.Path. It always returns
// a non-nil handler. If the path is not in its canonical form, the // a non-nil handler. If the path is not in its canonical form, the
// handler will be an internally-generated handler that redirects // handler will be an internally-generated handler that redirects
// to the canonical path. // to the canonical path. If the host contains a port, it is ignored
// when matching handlers.
//
// The path and host are used unchanged for CONNECT requests.
// //
// Handler also returns the registered pattern that matches the // Handler also returns the registered pattern that matches the
// request or, in the case of internally-generated redirects, // request or, in the case of internally-generated redirects,
...@@ -2204,16 +2220,24 @@ func (mux *ServeMux) match(path string) (h Handler, pattern string) { ...@@ -2204,16 +2220,24 @@ func (mux *ServeMux) match(path string) (h Handler, pattern string) {
// If there is no registered handler that applies to the request, // If there is no registered handler that applies to the request,
// Handler returns a ``page not found'' handler and an empty pattern. // Handler returns a ``page not found'' handler and an empty pattern.
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) { func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
if r.Method != "CONNECT" {
if p := cleanPath(r.URL.Path); p != r.URL.Path { // CONNECT requests are not canonicalized.
_, pattern = mux.handler(r.Host, p) if r.Method == "CONNECT" {
url := *r.URL return mux.handler(r.Host, r.URL.Path)
url.Path = p }
return RedirectHandler(url.String(), StatusMovedPermanently), pattern
} // All other requests have any port stripped and path cleaned
// before passing to mux.handler.
host := stripHostPort(r.Host)
path := cleanPath(r.URL.Path)
if path != r.URL.Path {
_, pattern = mux.handler(host, path)
url := *r.URL
url.Path = path
return RedirectHandler(url.String(), StatusMovedPermanently), pattern
} }
return mux.handler(r.Host, r.URL.Path) return mux.handler(host, r.URL.Path)
} }
// handler is the main implementation of Handler. // handler is the main implementation of Handler.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment