This function parses and validates a WebSocket URI.

    If the URI is valid, it returns a :class:`WebSocketURI`.

    Otherwise it raises an :exc:`~websockets.exceptions.InvalidURI` exception.

def parse_uri(uri: str) -> WebSocketURI:
    """
    This function parses and validates a WebSocket URI.

    If the URI is valid, it returns a :class:`WebSocketURI`.

    Otherwise it raises an :exc:`~websockets.exceptions.InvalidURI` exception.

    """
    parsed = urllib.parse.urlparse(uri)
    try:
        assert parsed.scheme in ["ws", "wss"]
        assert parsed.params == ""
        assert parsed.fragment == ""
        assert parsed.hostname is not None
    except AssertionError as exc:
        raise InvalidURI(uri) from exc

    secure = parsed.scheme == "wss"
    host = parsed.hostname
    port = parsed.port or (443 if secure else 80)
    resource_name = parsed.path or "/"
    if parsed.query:
        resource_name += "?" + parsed.query
    user_info = None
    if parsed.username or parsed.password:
        user_info = (parsed.username, parsed.password)
    return WebSocketURI(secure, host, port, resource_name, user_info)