path: str,
) -> typing.Tuple[typing.Pattern, str, typing.Dict[str, Convertor]]:
"""
- Given a path string, like: "/{username:str}", return a three-tuple
+ Given a path string, like: "/{username:str}",
+ or a host string, like: "{subdomain}.mydomain.org", return a three-tuple
of (regex, format, {param_name:convertor}).
regex: "/(?P<username>[^/]+)"
format: "/{username}"
convertors: {"username": StringConvertor()}
"""
+ is_host = not path.startswith("/")
+
path_regex = "^"
path_format = ""
duplicated_params = set()
ending = "s" if len(duplicated_params) > 1 else ""
raise ValueError(f"Duplicated param name{ending} {names} at path {path}")
- path_regex += re.escape(path[idx:].split(":")[0]) + "$"
+ if is_host:
+ # Align with `Host.matches()` behavior, which ignores port.
+ hostname = path[idx:].split(":")[0]
+ path_regex += re.escape(hostname) + "$"
+ else:
+ path_regex += re.escape(path[idx:]) + "$"
+
path_format += path[idx:]
return re.compile(path_regex), path_format, param_convertors
def __init__(
self, host: str, app: ASGIApp, name: typing.Optional[str] = None
) -> None:
+ assert not host.startswith("/"), "Host must not start with '/'"
self.host = host
self.app = app
self.name = name
return Response(content, media_type="text/plain")
+def disable_user(request):
+ content = "User " + request.path_params["username"] + " disabled"
+ return Response(content, media_type="text/plain")
+
+
def user_no_match(request): # pragma: no cover
content = "User fixed no match"
return Response(content, media_type="text/plain")
Route("/", endpoint=users),
Route("/me", endpoint=user_me),
Route("/{username}", endpoint=user),
+ Route("/{username}:disable", endpoint=disable_user, methods=["PUT"]),
Route("/nomatch", endpoint=user_no_match),
],
),
assert response.url == "http://testserver/users/tomchristie"
assert response.text == "User tomchristie"
+ response = client.put("/users/tomchristie:disable")
+ assert response.status_code == 200
+ assert response.url == "http://testserver/users/tomchristie:disable"
+ assert response.text == "User tomchristie disabled"
+
response = client.get("/users/nomatch")
assert response.status_code == 200
assert response.text == "User nomatch"
response = client.get("/")
assert response.status_code == 200
- client = test_client_factory(mixed_hosts_app, base_url="https://port.example.org/")
+ client = test_client_factory(
+ mixed_hosts_app, base_url="https://port.example.org:3600/"
+ )
response = client.get("/users")
assert response.status_code == 404
response = client.get("/")
assert response.status_code == 200
+ # Port in requested Host is irrelevant.
+
+ client = test_client_factory(mixed_hosts_app, base_url="https://port.example.org/")
+
+ response = client.get("/")
+ assert response.status_code == 200
+
client = test_client_factory(
mixed_hosts_app, base_url="https://port.example.org:5600/"
)