From 3396111f2dd6367c46565b7265cf15b8077bf136 Mon Sep 17 00:00:00 2001 From: oliver Date: Fri, 8 May 2026 11:36:06 +0800 Subject: [PATCH] =?UTF-8?q?fix(UME):=20=E6=8C=89=E7=8E=B0=E5=9C=BA?= =?UTF-8?q?=E5=AE=9E=E6=B5=8B=E8=B0=83=E6=95=B4=E8=AF=B7=E6=B1=82=E5=A4=B4?= =?UTF-8?q?=E5=B9=B6=E5=BC=BA=E5=88=B6HTTP/1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 请求头仅保留 content-type 与 accessToken,不再发送 accept/application - 统一通过 httpx.Client(http2=False) 调用,避免 UME 在 HTTP/2 下超时 Co-authored-by: Cursor --- netx_api/ume_client.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/netx_api/ume_client.py b/netx_api/ume_client.py index 9b281ad..af564ab 100644 --- a/netx_api/ume_client.py +++ b/netx_api/ume_client.py @@ -164,7 +164,6 @@ class UMEClient: def _headers(self, *, include_token: bool = True) -> dict[str, str]: headers = { - "accept": "application/yang-data+json", "content-type": self.content_type, } if include_token: @@ -173,6 +172,12 @@ class UMEClient: headers[self.auth_header] = token return headers + def _client(self) -> httpx.Client: + # Force HTTP/1.1 (disable HTTP/2) due to UME server compatibility issues. + # httpx defaults to HTTP/1.1 unless http2=True, but some environments still + # negotiate/behave unexpectedly; be explicit here. + return httpx.Client(verify=self.verify_tls, timeout=self.timeout_s, http2=False) + def _extract_token_and_ttl(self, payload: dict[str, Any]) -> tuple[str, int | None]: token = "" ttl: int | None = None @@ -229,7 +234,7 @@ class UMEClient: url = self._build_url(self.token_path) payload = {"login-info": {"user-name": self.username, "value": self.password}} try: - with httpx.Client(verify=self.verify_tls, timeout=self.timeout_s) as client: + with self._client() as client: resp = client.post(url, json=payload, headers=self._headers(include_token=False)) if not resp.is_success: raise RuntimeError(f"ume_login_failed:{resp.status_code}:{resp.text[:240]}") @@ -273,7 +278,7 @@ class UMEClient: return self.login(force=True) url = self._build_url(self.token_handshake_path) try: - with httpx.Client(verify=self.verify_tls, timeout=self.timeout_s) as client: + with self._client() as client: resp = client.post(url, headers=self._headers(include_token=True)) if not resp.is_success: # handshake may fail if token expired; fallback to full login @@ -307,7 +312,7 @@ class UMEClient: return True url = self._build_url(self.token_logout_path) try: - with httpx.Client(verify=self.verify_tls, timeout=self.timeout_s) as client: + with self._client() as client: resp = client.delete(url, headers=self._headers(include_token=True)) if resp.status_code in (401, 403): # Token already invalid/expired on server side can be treated as logged out. @@ -349,12 +354,12 @@ class UMEClient: retry_count = 0 t0 = time() try: - with httpx.Client(verify=self.verify_tls, timeout=self.timeout_s) as client: + with self._client() as client: resp = client.request(m, url, params=params, json=body, headers=self._headers(include_token=True)) if resp.status_code in (401, 403): retry_count = 1 self.login(force=True) - with httpx.Client(verify=self.verify_tls, timeout=self.timeout_s) as client: + with self._client() as client: resp = client.request(m, url, params=params, json=body, headers=self._headers(include_token=True)) if not resp.is_success: diag = RequestDiagnostics(