def _rest_request(self, method: str, endpoint: str, payload: Optional[dict] = None, timeout: Optional[int] = None) -> Optional[Any]: method = method.upper() if method not in ("POST", "PUT", "DELETE", "PATCH", "GET"): self._last_error = f"_rest_request: неподдерживаемый метод {method}" return None url = f"{self._base}/api/v2.0/{endpoint}" t = timeout if timeout is not None else self.valves.request_timeout try: r = requests.request(method, url, headers=self._headers, json=payload if payload is not None else {}, timeout=t, verify=self.valves.verify_ssl) # v2.1.2: автоматический fallback POST → GET при 405 (Method Not Allowed). # Это часто встречается в TrueNAS 25.10: некоторые эндпоинты каталога # исторически были POST, но в новых версиях стали GET. if r.status_code == 405 and method == "POST": try: r2 = requests.get(url, headers=self._headers, params=payload or {}, timeout=t, verify=self.valves.verify_ssl) if r2.status_code in (200, 201, 202, 204): if not r2.text: return {"status": "ok", "http_code": r2.status_code, "via": "GET-fallback"} try: data = r2.json() if isinstance(data, dict): data["_via"] = "GET-fallback" return data except Exception: return {"status": "ok", "text": r2.text, "http_code": r2.status_code, "_via": "GET-fallback"} except Exception: pass # вернёмся к исходной ошибке ниже if r.status_code in (200, 201, 202, 204): if not r.text: return {"status": "ok", "http_code": r.status_code} try: return r.json() except Exception: return {"status": "ok", "text": r.text, "http_code": r.status_code} self._last_error = f"{method} {endpoint} → HTTP {r.status_code}: {r.text[:400]}" return None except requests.exceptions.SSLError as e: self._last_error = f"SSL-ошибка {method} {endpoint}: {e}" return None except requests.exceptions.ConnectionError as e: self._last_error = f"Соединение {method} {endpoint}: {e}" return None except requests.exceptions.Timeout: self._last_error = f"Таймаут {method} {endpoint} (> {t}с)" return None except Exception as e: self._last_error = f"{method} {endpoint}: {type(e).__name__}: {e}" return None