08ea5fbe98
添加用户管理视图、API和状态管理文件
239 lines
6.8 KiB
Python
239 lines
6.8 KiB
Python
"""
|
|
API客户端模块
|
|
|
|
提供HTTP请求封装和API调用功能。
|
|
"""
|
|
|
|
import requests
|
|
import json
|
|
from typing import Any, Dict, Optional, Callable
|
|
from dataclasses import dataclass
|
|
from enum import Enum
|
|
|
|
|
|
class HTTPMethod(Enum):
|
|
"""HTTP方法"""
|
|
GET = "GET"
|
|
POST = "POST"
|
|
PUT = "PUT"
|
|
DELETE = "DELETE"
|
|
PATCH = "PATCH"
|
|
|
|
|
|
@dataclass
|
|
class APIResponse:
|
|
"""API响应"""
|
|
status_code: int
|
|
data: Any
|
|
headers: Dict[str, str]
|
|
success: bool
|
|
error_message: Optional[str] = None
|
|
|
|
|
|
@dataclass
|
|
class APIRequest:
|
|
"""API请求"""
|
|
method: HTTPMethod
|
|
url: str
|
|
headers: Optional[Dict[str, str]] = None
|
|
params: Optional[Dict[str, Any]] = None
|
|
data: Optional[Any] = None
|
|
json_data: Optional[Dict[str, Any]] = None
|
|
timeout: int = 30
|
|
|
|
|
|
class APIClient:
|
|
"""
|
|
API客户端
|
|
|
|
特性:
|
|
- 支持多种HTTP方法
|
|
- 自动JSON序列化/反序列化
|
|
- 超时处理
|
|
- 错误处理
|
|
- 请求/响应拦截器
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
base_url: str,
|
|
default_headers: Optional[Dict[str, str]] = None,
|
|
timeout: int = 30
|
|
):
|
|
"""
|
|
初始化API客户端
|
|
|
|
Args:
|
|
base_url: 基础URL
|
|
default_headers: 默认请求头
|
|
timeout: 默认超时时间(秒)
|
|
"""
|
|
self._base_url = base_url.rstrip('/')
|
|
self._default_headers = default_headers or {}
|
|
self._default_timeout = timeout
|
|
self._request_interceptors: list = []
|
|
self._response_interceptors: list = []
|
|
self._session = requests.Session()
|
|
|
|
def add_request_interceptor(self, interceptor: Callable[[APIRequest], APIRequest]) -> None:
|
|
"""添加请求拦截器"""
|
|
self._request_interceptors.append(interceptor)
|
|
|
|
def add_response_interceptor(self, interceptor: Callable[[APIResponse], APIResponse]) -> None:
|
|
"""添加响应拦截器"""
|
|
self._response_interceptors.append(interceptor)
|
|
|
|
def _build_url(self, endpoint: str) -> str:
|
|
"""构建完整URL"""
|
|
endpoint = endpoint.lstrip('/')
|
|
return f"{self._base_url}/{endpoint}"
|
|
|
|
def _apply_request_interceptors(self, request: APIRequest) -> APIRequest:
|
|
"""应用请求拦截器"""
|
|
for interceptor in self._request_interceptors:
|
|
request = interceptor(request)
|
|
return request
|
|
|
|
def _apply_response_interceptors(self, response: APIResponse) -> APIResponse:
|
|
"""应用响应拦截器"""
|
|
for interceptor in self._response_interceptors:
|
|
response = interceptor(response)
|
|
return response
|
|
|
|
def request(self, api_request: APIRequest) -> APIResponse:
|
|
"""
|
|
发送HTTP请求
|
|
|
|
Args:
|
|
api_request: API请求对象
|
|
|
|
Returns:
|
|
API响应对象
|
|
"""
|
|
try:
|
|
# 应用请求拦截器
|
|
api_request = self._apply_request_interceptors(api_request)
|
|
|
|
# 合并默认请求头
|
|
headers = {**self._default_headers, **(api_request.headers or {})}
|
|
|
|
# 发送请求
|
|
response = self._session.request(
|
|
method=api_request.method.value,
|
|
url=api_request.url,
|
|
headers=headers,
|
|
params=api_request.params,
|
|
data=api_request.data,
|
|
json=api_request.json_data,
|
|
timeout=api_request.timeout or self._default_timeout
|
|
)
|
|
|
|
# 解析响应
|
|
try:
|
|
response_data = response.json()
|
|
except json.JSONDecodeError:
|
|
response_data = response.text
|
|
|
|
api_response = APIResponse(
|
|
status_code=response.status_code,
|
|
data=response_data,
|
|
headers=dict(response.headers),
|
|
success=200 <= response.status_code < 300
|
|
)
|
|
|
|
# 应用响应拦截器
|
|
return self._apply_response_interceptors(api_response)
|
|
|
|
except requests.exceptions.Timeout:
|
|
return APIResponse(
|
|
status_code=0,
|
|
data=None,
|
|
headers={},
|
|
success=False,
|
|
error_message="请求超时"
|
|
)
|
|
except requests.exceptions.ConnectionError as e:
|
|
return APIResponse(
|
|
status_code=0,
|
|
data=None,
|
|
headers={},
|
|
success=False,
|
|
error_message=f"连接错误: {str(e)}"
|
|
)
|
|
except Exception as e:
|
|
return APIResponse(
|
|
status_code=0,
|
|
data=None,
|
|
headers={},
|
|
success=False,
|
|
error_message=f"请求失败: {str(e)}"
|
|
)
|
|
|
|
def get(
|
|
self,
|
|
endpoint: str,
|
|
params: Optional[Dict[str, Any]] = None,
|
|
headers: Optional[Dict[str, str]] = None,
|
|
timeout: Optional[int] = None
|
|
) -> APIResponse:
|
|
"""发送GET请求"""
|
|
request = APIRequest(
|
|
method=HTTPMethod.GET,
|
|
url=self._build_url(endpoint),
|
|
headers=headers,
|
|
params=params,
|
|
timeout=timeout or self._default_timeout
|
|
)
|
|
return self.request(request)
|
|
|
|
def post(
|
|
self,
|
|
endpoint: str,
|
|
json_data: Optional[Dict[str, Any]] = None,
|
|
data: Optional[Any] = None,
|
|
headers: Optional[Dict[str, str]] = None,
|
|
timeout: Optional[int] = None
|
|
) -> APIResponse:
|
|
"""发送POST请求"""
|
|
request = APIRequest(
|
|
method=HTTPMethod.POST,
|
|
url=self._build_url(endpoint),
|
|
headers=headers,
|
|
data=data,
|
|
json_data=json_data,
|
|
timeout=timeout or self._default_timeout
|
|
)
|
|
return self.request(request)
|
|
|
|
def put(
|
|
self,
|
|
endpoint: str,
|
|
json_data: Optional[Dict[str, Any]] = None,
|
|
headers: Optional[Dict[str, str]] = None,
|
|
timeout: Optional[int] = None
|
|
) -> APIResponse:
|
|
"""发送PUT请求"""
|
|
request = APIRequest(
|
|
method=HTTPMethod.PUT,
|
|
url=self._build_url(endpoint),
|
|
headers=headers,
|
|
json_data=json_data,
|
|
timeout=timeout or self._default_timeout
|
|
)
|
|
return self.request(request)
|
|
|
|
def delete(
|
|
self,
|
|
endpoint: str,
|
|
headers: Optional[Dict[str, str]] = None,
|
|
timeout: Optional[int] = None
|
|
) -> APIResponse:
|
|
"""发送DELETE请求"""
|
|
request = APIRequest(
|
|
method=HTTPMethod.DELETE,
|
|
url=self._build_url(endpoint),
|
|
headers=headers,
|
|
timeout=timeout or self._default_timeout
|
|
)
|
|
return self.request(request)
|