unistore_http/lib.rs
1//! # unistore-http: HTTP 客户端能力
2//!
3//! 提供开箱即用的 HTTP 客户端,支持自动重试和超时控制。
4//!
5//! ## 设计哲学
6//!
7//! **三层 API 设计**:从简单到复杂,满足不同场景需求。
8//!
9//! ```text
10//! ┌─────────────────────────────────────────────────────────────────┐
11//! │ Level 3: 便捷函数(一行代码) │
12//! │ get(url) / post_json(url, body) │
13//! ├─────────────────────────────────────────────────────────────────┤
14//! │ Level 2: HttpClient(带配置的客户端) │
15//! │ HttpClient::new() / HttpClient::builder() │
16//! ├─────────────────────────────────────────────────────────────────┤
17//! │ Level 1: 底层访问(完全控制) │
18//! │ client.inner() -> &reqwest::Client │
19//! └─────────────────────────────────────────────────────────────────┘
20//! ```
21//!
22//! ## 快速开始
23//!
24//! ```ignore
25//! use unistore_http::{get, get_json, HttpClient};
26//!
27//! // Level 3: 便捷函数
28//! let body = get("https://api.example.com/status").await?.text()?;
29//! let user: User = get_json("https://api.example.com/user/1").await?;
30//!
31//! // Level 2: 客户端实例
32//! let client = HttpClient::builder()
33//! .timeout(Duration::from_secs(60))
34//! .max_retries(5)
35//! .build()?;
36//! let resp = client.get("https://api.example.com/data").await?;
37//! ```
38
39// ============================================================================
40// 内部模块
41// ============================================================================
42
43mod client;
44mod config;
45mod error;
46mod facade;
47mod request;
48mod response;
49
50// ============================================================================
51// 公开 API(sdk.rs 职责整合到 lib.rs)
52// ============================================================================
53
54// 核心类型
55pub use client::HttpClient;
56pub use config::{HttpClientConfig, HttpClientConfigBuilder, ProxyConfig, RetryStrategy};
57pub use error::HttpError;
58pub use response::Response;
59
60// 请求构建
61pub use request::{
62 CancellableRequest, CancellationToken, CancellationTrigger,
63 Method, RequestBuilder, cancellation_pair,
64};
65
66// 便捷函数(Level 3 API)
67pub use facade::{
68 delete, get, get_bytes, get_json, get_text, head, patch_json, post_form, post_json,
69 post_json_for_json, put_json,
70};
71
72// ============================================================================
73// Capability 实现
74// ============================================================================
75
76use async_trait::async_trait;
77use unistore_core::{Capability, CapabilityError, CapabilityInfo};
78
79/// HTTP 客户端能力
80///
81/// 实现 `Capability` trait,可被 UniStore 运行时管理
82pub struct HttpCapability {
83 client: Option<HttpClient>,
84 config: HttpClientConfig,
85}
86
87impl HttpCapability {
88 /// 创建 HTTP 能力实例
89 pub fn new() -> Self {
90 Self {
91 client: None,
92 config: HttpClientConfig::default(),
93 }
94 }
95
96 /// 使用自定义配置创建
97 pub fn with_config(config: HttpClientConfig) -> Self {
98 Self {
99 client: None,
100 config,
101 }
102 }
103
104 /// 获取客户端(能力必须已启动)
105 pub fn client(&self) -> Option<&HttpClient> {
106 self.client.as_ref()
107 }
108}
109
110impl Default for HttpCapability {
111 fn default() -> Self {
112 Self::new()
113 }
114}
115
116#[async_trait]
117impl Capability for HttpCapability {
118 fn info(&self) -> CapabilityInfo {
119 CapabilityInfo::new("http", env!("CARGO_PKG_VERSION"))
120 .with_description("HTTP client capability with retry and timeout support")
121 .with_author("UniStore Team")
122 }
123
124 async fn start(&mut self) -> Result<(), CapabilityError> {
125 if self.client.is_some() {
126 return Ok(()); // 已启动
127 }
128
129 let client = HttpClient::with_config(self.config.clone())
130 .map_err(|e| CapabilityError::start_failed("http", e.to_string()))?;
131 self.client = Some(client);
132 Ok(())
133 }
134
135 async fn stop(&mut self) -> Result<(), CapabilityError> {
136 self.client = None;
137 Ok(())
138 }
139
140 async fn health_check(&self) -> Result<(), CapabilityError> {
141 if self.client.is_none() {
142 return Err(CapabilityError::unhealthy("http", "客户端未初始化"));
143 }
144 Ok(())
145 }
146}