Files

37 lines
1.1 KiB
Python

"""URL construction shared by every sub-server.
An identifier joined into a path unencoded is not sent as itself: httpx resolves
the URL per RFC 3986, so "../" walks the request onto another endpoint.
"""
from urllib.parse import quote
_DOT_SEGMENTS = frozenset({".", ".."})
def path_segment(value: str) -> str:
"""Encode one path segment, so an identifier names a resource and nothing else.
Args:
value: The segment to encode, taken as a name in full.
Returns:
The segment percent-encoded, with the dots escaped when it is only dots.
"""
encoded = quote(value, safe="")
# A dot is legal in a name, so `quote` keeps it: a segment of nothing but
# dots would still resolve away rather than name anything.
return encoded.replace(".", "%2E") if encoded in _DOT_SEGMENTS else encoded
def url_path(*segments: str) -> str:
"""Build a URL path from one argument per segment, each of them encoded.
Args:
*segments: The path segments, in order.
Returns:
The joined path, with a leading slash.
"""
return "/" + "/".join(path_segment(segment) for segment in segments)