unistore-http 0.1.0

HTTP client capability for UniStore
Documentation
//! # unistore-http: HTTP 客户端能力
//!
//! 提供开箱即用的 HTTP 客户端,支持自动重试和超时控制。
//!
//! ## 设计哲学
//!
//! **三层 API 设计**:从简单到复杂,满足不同场景需求。
//!
//! ```text
//! ┌─────────────────────────────────────────────────────────────────┐
//! │  Level 3: 便捷函数(一行代码)                                   │
//! │  get(url) / post_json(url, body)                               │
//! ├─────────────────────────────────────────────────────────────────┤
//! │  Level 2: HttpClient(带配置的客户端)                          │
//! │  HttpClient::new() / HttpClient::builder()                     │
//! ├─────────────────────────────────────────────────────────────────┤
//! │  Level 1: 底层访问(完全控制)                                   │
//! │  client.inner() -> &reqwest::Client                            │
//! └─────────────────────────────────────────────────────────────────┘
//! ```
//!
//! ## 快速开始
//!
//! ```ignore
//! use unistore_http::{get, get_json, HttpClient};
//!
//! // Level 3: 便捷函数
//! let body = get("https://api.example.com/status").await?.text()?;
//! let user: User = get_json("https://api.example.com/user/1").await?;
//!
//! // Level 2: 客户端实例
//! let client = HttpClient::builder()
//!     .timeout(Duration::from_secs(60))
//!     .max_retries(5)
//!     .build()?;
//! let resp = client.get("https://api.example.com/data").await?;
//! ```

// ============================================================================
// 内部模块
// ============================================================================

mod client;
mod config;
mod error;
mod facade;
mod request;
mod response;

// ============================================================================
// 公开 API(sdk.rs 职责整合到 lib.rs)
// ============================================================================

// 核心类型
pub use client::HttpClient;
pub use config::{HttpClientConfig, HttpClientConfigBuilder, ProxyConfig, RetryStrategy};
pub use error::HttpError;
pub use response::Response;

// 请求构建
pub use request::{
    CancellableRequest, CancellationToken, CancellationTrigger,
    Method, RequestBuilder, cancellation_pair,
};

// 便捷函数(Level 3 API)
pub use facade::{
    delete, get, get_bytes, get_json, get_text, head, patch_json, post_form, post_json,
    post_json_for_json, put_json,
};

// ============================================================================
// Capability 实现
// ============================================================================

use async_trait::async_trait;
use unistore_core::{Capability, CapabilityError, CapabilityInfo};

/// HTTP 客户端能力
///
/// 实现 `Capability` trait,可被 UniStore 运行时管理
pub struct HttpCapability {
    client: Option<HttpClient>,
    config: HttpClientConfig,
}

impl HttpCapability {
    /// 创建 HTTP 能力实例
    pub fn new() -> Self {
        Self {
            client: None,
            config: HttpClientConfig::default(),
        }
    }

    /// 使用自定义配置创建
    pub fn with_config(config: HttpClientConfig) -> Self {
        Self {
            client: None,
            config,
        }
    }

    /// 获取客户端(能力必须已启动)
    pub fn client(&self) -> Option<&HttpClient> {
        self.client.as_ref()
    }
}

impl Default for HttpCapability {
    fn default() -> Self {
        Self::new()
    }
}

#[async_trait]
impl Capability for HttpCapability {
    fn info(&self) -> CapabilityInfo {
        CapabilityInfo::new("http", env!("CARGO_PKG_VERSION"))
            .with_description("HTTP client capability with retry and timeout support")
            .with_author("UniStore Team")
    }

    async fn start(&mut self) -> Result<(), CapabilityError> {
        if self.client.is_some() {
            return Ok(()); // 已启动
        }

        let client = HttpClient::with_config(self.config.clone())
            .map_err(|e| CapabilityError::start_failed("http", e.to_string()))?;
        self.client = Some(client);
        Ok(())
    }

    async fn stop(&mut self) -> Result<(), CapabilityError> {
        self.client = None;
        Ok(())
    }

    async fn health_check(&self) -> Result<(), CapabilityError> {
        if self.client.is_none() {
            return Err(CapabilityError::unhealthy("http", "客户端未初始化"));
        }
        Ok(())
    }
}