70 lines
2.1 KiB
Python
70 lines
2.1 KiB
Python
"""帧编解码与注册地址推导。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import Any
|
|
from urllib.parse import urlparse, urlunparse
|
|
|
|
|
|
def dumps(obj: dict[str, Any]) -> bytes:
|
|
return json.dumps(obj, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
|
|
|
|
|
|
def loads(data: bytes | str) -> dict[str, Any]:
|
|
if isinstance(data, bytes):
|
|
data = data.decode("utf-8")
|
|
return json.loads(data)
|
|
|
|
|
|
def register_url_from_connect(connect_url: str) -> str:
|
|
"""从连接地址推出注册 HTTP 地址(DEVELOPMENT 6.9)。"""
|
|
raw = connect_url.strip()
|
|
if "://" not in raw:
|
|
raw = "ws://" + raw
|
|
u = urlparse(raw)
|
|
scheme = u.scheme.lower()
|
|
if scheme in ("wss", "mqtts", "https"):
|
|
http_scheme = "https"
|
|
elif scheme in ("ws", "mqtt", "http"):
|
|
http_scheme = "http"
|
|
else:
|
|
http_scheme = "https" if scheme.endswith("s") else "http"
|
|
# 去掉 /mqtt 路径
|
|
path = u.path or ""
|
|
if path.endswith("/mqtt"):
|
|
path = path[: -len("/mqtt")]
|
|
path = path.rstrip("/") + "/api/client/register"
|
|
return urlunparse((http_scheme, u.netloc, path, "", "", ""))
|
|
|
|
|
|
def up_topic(endpoint_id: str) -> str:
|
|
return f"nix/c/{endpoint_id}/up"
|
|
|
|
|
|
def down_topic(endpoint_id: str) -> str:
|
|
return f"nix/c/{endpoint_id}/down"
|
|
|
|
|
|
def normalize_mqtt_ws_url(url: str, *, allow_tcp: bool = False) -> str:
|
|
"""http→ws、https→wss;路径为空或 / 时用 /mqtt,否则保留;mqtt/mqtts 仅显式允许裸 TCP。"""
|
|
raw = url.strip()
|
|
if "://" not in raw:
|
|
raw = "ws://" + raw
|
|
u = urlparse(raw)
|
|
scheme = u.scheme.lower()
|
|
if scheme == "http":
|
|
scheme = "ws"
|
|
elif scheme == "https":
|
|
scheme = "wss"
|
|
if scheme in ("mqtt", "mqtts"):
|
|
if not allow_tcp:
|
|
raise ValueError("裸 TCP 需显式 use_tcp")
|
|
return urlunparse((scheme, u.netloc, u.path, u.params, u.query, u.fragment))
|
|
if scheme not in ("ws", "wss"):
|
|
raise ValueError(f"unsupported scheme {u.scheme}")
|
|
path = u.path or ""
|
|
if path in ("", "/"):
|
|
path = "/mqtt"
|
|
return urlunparse((scheme, u.netloc, path, u.params, u.query, u.fragment))
|