Repository: gorilla/mux
Pull request #447 (2019-02-13 00:26:02)

Route.Host -matching will ignore any provided port from getHost(), if…
… a port isn't specified in the template

In lieu of checking the template pattern on every Match request, a bool is added to the routeRegexp, and set if the routeRegexp is a host AND there is no ":" in the template. I dislike extending the type, but I'd dislike doing a string match on every single Match, even more.

All existing mux tests pass. Additionally my application-level (Convey) positive and negative tests pass. Feel free to comment: You know your code better than I do.

```
=== RUN   TestPathHostPortUnset

  When a request is made, with a host and port specified, the correct match is found (no port specified) ✔✔✔✔✔


16 total assertions

--- PASS: TestPathHostPortUnset (0.00s)
=== RUN   TestPathHostPortSet

  When a request is made, with a host and port specified, and the port does match, a match is found ✔✔✔✔✔


21 total assertions

--- PASS: TestPathHostPortSet (0.00s)
=== RUN   TestPathHostPortSetNope

  When a request is made, with a host and port specified, and the port does not match, a match is NOT found ✔✔✔


24 total assertions

--- PASS: TestPathHostPortSetNope (0.00s)

```


Patch:
diff --git a/.travis.yml b/.travis.yml
index 0e58a72..d003ad9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,5 @@
 language: go
-sudo: false
+
 
 matrix:
   include:
@@ -20,5 +20,5 @@ install:
 script:
   - go get -t -v ./...
   - diff -u <(echo -n) <(gofmt -d .)
-  - if [[ "$LATEST" = true ]]; then go tool vet .; fi
+  - if [[ "$LATEST" = true ]]; then go vet .; fi
   - go test -v -race ./...
diff --git a/mux.go b/mux.go
index 8aca972..a2cd193 100644
--- a/mux.go
+++ b/mux.go
@@ -283,6 +283,12 @@ func (r *Router) NewRoute() *Route {
 	return route
 }
 
+// Name registers a new route with a name.
+// See Route.Name().
+func (r *Router) Name(name string) *Route {
+	return r.NewRoute().Name(name)
+}
+
 // Handle registers a new route with a matcher for the URL path.
 // See Route.Path() and Route.Handler().
 func (r *Router) Handle(path string, handler http.Handler) *Route {
diff --git a/regexp.go b/regexp.go
index f252886..ac1abcd 100644
--- a/regexp.go
+++ b/regexp.go
@@ -113,6 +113,13 @@ func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*ro
 	if typ != regexpTypePrefix {
 		pattern.WriteByte('$')
 	}
+
+	var wildcardHostPort bool
+	if typ == regexpTypeHost {
+		if !strings.Contains(pattern.String(), ":") {
+			wildcardHostPort = true
+		}
+	}
 	reverse.WriteString(raw)
 	if endSlash {
 		reverse.WriteByte('/')
@@ -131,13 +138,14 @@ func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*ro
 
 	// Done!
 	return &routeRegexp{
-		template:   template,
-		regexpType: typ,
-		options:    options,
-		regexp:     reg,
-		reverse:    reverse.String(),
-		varsN:      varsN,
-		varsR:      varsR,
+		template:         template,
+		regexpType:       typ,
+		options:          options,
+		regexp:           reg,
+		reverse:          reverse.String(),
+		varsN:            varsN,
+		varsR:            varsR,
+		wildcardHostPort: wildcardHostPort,
 	}, nil
 }
 
@@ -158,11 +166,22 @@ type routeRegexp struct {
 	varsN []string
 	// Variable regexps (validators).
 	varsR []*regexp.Regexp
+	// Wildcard host-port (no strict port match in hostname)
+	wildcardHostPort bool
 }
 
 // Match matches the regexp against the URL host or path.
 func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {
-	if r.regexpType != regexpTypeHost {
+	if r.regexpType == regexpTypeHost {
+		host := getHost(req)
+		if r.wildcardHostPort {
+			// Don't be strict on the port match
+			if i := strings.Index(host, ":"); i != -1 {
+				host = host[:i]
+			}
+		}
+		return r.regexp.MatchString(host)
+	} else {
 		if r.regexpType == regexpTypeQuery {
 			return r.matchQueryString(req)
 		}
@@ -172,8 +191,6 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {
 		}
 		return r.regexp.MatchString(path)
 	}
-
-	return r.regexp.MatchString(getHost(req))
 }
 
 // url builds a URL part using the given values.
diff --git a/route.go b/route.go
index 16a7cdf..8479c68 100644
--- a/route.go
+++ b/route.go
@@ -383,7 +383,7 @@ func (r *Route) PathPrefix(tpl string) *Route {
 // The above route will only match if the URL contains the defined queries
 // values, e.g.: ?foo=bar&id=42.
 //
-// It the value is an empty string, it will match any value if the key is set.
+// If the value is an empty string, it will match any value if the key is set.
 //
 // Variables can define an optional regexp pattern to be matched:
 //


Test patch:
diff --git a/mux_test.go b/mux_test.go
index 61653d7..f5c1e9c 100644
--- a/mux_test.go
+++ b/mux_test.go
@@ -1441,10 +1441,11 @@ func TestNamedRoutes(t *testing.T) {
 	r3.NewRoute().Name("g")
 	r3.NewRoute().Name("h")
 	r3.NewRoute().Name("i")
+	r3.Name("j")
 
-	if r1.namedRoutes == nil || len(r1.namedRoutes) != 9 {
-		t.Errorf("Expected 9 named routes, got %v", r1.namedRoutes)
-	} else if r1.Get("i") == nil {
+	if r1.namedRoutes == nil || len(r1.namedRoutes) != 10 {
+		t.Errorf("Expected 10 named routes, got %v", r1.namedRoutes)
+	} else if r1.Get("j") == nil {
 		t.Errorf("Subroute name not registered")
 	}
 }