# # Copyright 2026 The InfiniFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from dataclasses import dataclass from typing import Any import pytest import requests from test.testcases.configs import HOST_ADDRESS, IS_GO_PROXY, VERSION @dataclass class RestClient: token: str | None = None timeout: int = 30 @property def api_root(self) -> str: return f"{HOST_ADDRESS}/api/{VERSION}" def _headers(self, headers: dict[str, str] | None = None) -> dict[str, str]: merged: dict[str, str] = {"Content-Type": "application/json"} if headers: merged.update(headers) if self.token and "Authorization" not in merged: merged["Authorization"] = f"Bearer {self.token}" return merged def request( self, method: str, path: str, *, headers: dict[str, str] | None = None, params: dict[str, Any] | None = None, json: dict[str, Any] | None = None, data: Any = None, files: Any = None, **request_kwargs: Any, ) -> requests.Response: req_headers = self._headers(headers) if files is not None: # requests sets multipart boundary automatically. req_headers.pop("Content-Type", None) timeout = request_kwargs.pop("timeout", self.timeout) normalized_path = f"/{path.lstrip('/')}" if path else "/" response = requests.request( method=method, url=f"{self.api_root}{normalized_path}", headers=req_headers, params=params, json=json, data=data, files=files, timeout=timeout, **request_kwargs, ) if IS_GO_PROXY: try: payload = response.json() except ValueError: return response if not isinstance(payload, dict): return response message = payload.get("message", "") if payload.get("code") == 500 and "Unknown column 'meta_fields'" in message: pytest.skip("Go deployment database schema is missing document.meta_fields") if payload.get("code") == 500 and "http://localhost:6380/embed" in message and "connect: connection refused" in message: pytest.skip("Go memory embedding service is unavailable on localhost:6380") return response def get(self, path: str, **kwargs) -> requests.Response: return self.request("GET", path, **kwargs) def post(self, path: str, **kwargs) -> requests.Response: return self.request("POST", path, **kwargs) def delete(self, path: str, **kwargs) -> requests.Response: return self.request("DELETE", path, **kwargs) def put(self, path: str, **kwargs) -> requests.Response: return self.request("PUT", path, **kwargs) def patch(self, path: str, **kwargs) -> requests.Response: return self.request("PATCH", path, **kwargs)