Repository: pallets/werkzeug

Issue:
Building urls with host_matching Map does not produce host based URLs
``` python

>>> from werkzeug import routing as r
>>> m = r.Map([
...   r.Rule('/', endpoint='index', host='www.domain.com'),
...   r.Rule('/', endpoint='index', host='my.domain.com'),
... ], host_matching=True)
>>> www = m.bind('www.domain.com')
>>> my = m.bind('my.domain.com')
>>> www.match('/')
('index', {})
>>> my.match('/')
('index', {})
```

When building

``` python
>>> www.build('index')
'/'
>>> my.build('index')
'http://www.domain.com/'
```



Discussion:
Straight from the documentation for `MapAdapter.build`:

> Per default external URLs (include the server name) will only be used if the target URL is on a different subdomain.

Since your two rules have the same endpoint, they get viewed as identical. If you register the rules in reverse order, you get this:

```
>>> www.build('index')
'http://my.domain.com/'
>>> my.build('index')
'/'
```

But i can definetly see why this would be considered a bug.

There are two viable solutions to this issue that I can surmise and I am looking for feedback on the most appropriate option.

1. Do not allow the same endpoint value to be used for two routes. I would propose a `ValueError` to be raised when it occurs. This option would reduce confusion as the first match is always returned and that may not be the expected result.
2. Check for and favor a host match for all rules that match the endpoint in a build call.

Resolving patch:
diff --git a/src/werkzeug/routing.py b/src/werkzeug/routing.py
--- a/src/werkzeug/routing.py
+++ b/src/werkzeug/routing.py
@@ -1932,13 +1932,25 @@ def _partial_build(self, endpoint, values, method, append_unknown):
             if rv is not None:
                 return rv
 
-        # default method did not match or a specific method is passed,
-        # check all and go with first result.
+        # Default method did not match or a specific method is passed.
+        # Check all for first match with matching host. If no matching
+        # host is found, go with first result.
+        first_match = None
+
         for rule in self.map._rules_by_endpoint.get(endpoint, ()):
             if rule.suitable_for(values, method):
                 rv = rule.build(values, append_unknown)
+
                 if rv is not None:
-                    return rv
+                    if self.map.host_matching:
+                        if rv[0] == self.server_name:
+                            return rv
+                        elif first_match is None:
+                            first_match = rv
+                    else:
+                        return rv
+
+        return first_match
 
     def build(
         self,


Test patch:
diff --git a/tests/test_routing.py b/tests/test_routing.py
--- a/tests/test_routing.py
+++ b/tests/test_routing.py
@@ -1131,3 +1131,28 @@ def test_build_url_with_arg_keyword():
 
     ret = adapter.build("foo", {"class": "bar"})
     assert ret == "http://example.org/foo/bar"
+
+
+def test_build_url_same_endpoint_multiple_hosts():
+    m = r.Map(
+        [
+            r.Rule("/", endpoint="index", host="alpha.example.com"),
+            r.Rule("/", endpoint="index", host="beta.example.com"),
+            r.Rule("/", endpoint="gamma", host="gamma.example.com"),
+        ],
+        host_matching=True,
+    )
+
+    alpha = m.bind("alpha.example.com")
+    assert alpha.build("index") == "/"
+    assert alpha.build("gamma") == "http://gamma.example.com/"
+
+    alpha_case = m.bind("AlPhA.ExAmPlE.CoM")
+    assert alpha_case.build("index") == "/"
+    assert alpha_case.build("gamma") == "http://gamma.example.com/"
+
+    beta = m.bind("beta.example.com")
+    assert beta.build("index") == "/"
+
+    beta_case = m.bind("BeTa.ExAmPlE.CoM")
+    assert beta_case.build("index") == "/"