unistore-http 0.1.0

HTTP client capability for UniStore
Documentation
//! HTTP 便捷函数门面
//!
//! 职责:
//! - 提供全局默认客户端
//! - 提供一行代码完成请求的便捷函数
//! - Level 3 API:最简单的使用方式

use super::client::HttpClient;
use super::error::HttpError;
use super::response::Response;
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::sync::OnceLock;

/// 全局默认客户端(惰性初始化)
static DEFAULT_CLIENT: OnceLock<HttpClient> = OnceLock::new();

/// 获取或初始化全局默认客户端
///
/// 首次调用时初始化,后续调用返回同一实例
fn default_client() -> Result<&'static HttpClient, HttpError> {
    if DEFAULT_CLIENT.get().is_none() {
        let client = HttpClient::new()?;
        // 忽略重复初始化的结果(可能有并发初始化)
        let _ = DEFAULT_CLIENT.set(client);
    }

    DEFAULT_CLIENT.get().ok_or(HttpError::Other("客户端初始化失败".to_string()))
}

/// 快捷 GET 请求
///
/// # Example
///
/// ```ignore
/// use unistore_http::get;
///
/// let response = get("https://api.example.com/status").await?;
/// let body = response.text()?;
/// ```
pub async fn get(url: &str) -> Result<Response, HttpError> {
    default_client()?.get(url).await
}

/// 快捷 GET 请求并解析为 JSON
///
/// # Example
///
/// ```ignore
/// use unistore_http::get_json;
///
/// #[derive(Deserialize)]
/// struct User {
///     name: String,
///     email: String,
/// }
///
/// let user: User = get_json("https://api.example.com/user/1").await?;
/// ```
pub async fn get_json<T: DeserializeOwned>(url: &str) -> Result<T, HttpError> {
    default_client()?.get(url).await?.into_json()
}

/// 快捷 GET 请求并获取文本
///
/// # Example
///
/// ```ignore
/// let html = get_text("https://example.com").await?;
/// ```
pub async fn get_text(url: &str) -> Result<String, HttpError> {
    default_client()?.get(url).await?.into_text()
}

/// 快捷 GET 请求并获取字节
///
/// # Example
///
/// ```ignore
/// let bytes = get_bytes("https://example.com/image.png").await?;
/// ```
pub async fn get_bytes(url: &str) -> Result<Vec<u8>, HttpError> {
    Ok(default_client()?.get(url).await?.into_bytes())
}

/// 快捷 POST 请求(JSON body)
///
/// # Example
///
/// ```ignore
/// use unistore_http::post_json;
///
/// #[derive(Serialize)]
/// struct CreateUser {
///     name: String,
///     email: String,
/// }
///
/// let user = CreateUser {
///     name: "Alice".into(),
///     email: "alice@example.com".into(),
/// };
///
/// let response = post_json("https://api.example.com/users", &user).await?;
/// ```
pub async fn post_json<T: Serialize>(url: &str, body: &T) -> Result<Response, HttpError> {
    default_client()?.post_json(url, body).await
}

/// 快捷 POST 请求(JSON body)并解析响应为 JSON
///
/// # Example
///
/// ```ignore
/// let created_user: User = post_json_for_json(
///     "https://api.example.com/users",
///     &new_user
/// ).await?;
/// ```
pub async fn post_json_for_json<T: Serialize, R: DeserializeOwned>(
    url: &str,
    body: &T,
) -> Result<R, HttpError> {
    default_client()?.post_json(url, body).await?.into_json()
}

/// 快捷 POST 请求(表单 body)
///
/// # Example
///
/// ```ignore
/// use unistore_http::post_form;
///
/// #[derive(Serialize)]
/// struct LoginForm {
///     username: String,
///     password: String,
/// }
///
/// let form = LoginForm {
///     username: "alice".into(),
///     password: "secret".into(),
/// };
///
/// let response = post_form("https://example.com/login", &form).await?;
/// ```
pub async fn post_form<T: Serialize>(url: &str, body: &T) -> Result<Response, HttpError> {
    default_client()?.post_form(url, body).await
}

/// 快捷 PUT 请求(JSON body)
///
/// # Example
///
/// ```ignore
/// let response = put_json(
///     "https://api.example.com/users/1",
///     &updated_user
/// ).await?;
/// ```
pub async fn put_json<T: Serialize>(url: &str, body: &T) -> Result<Response, HttpError> {
    default_client()?.put_json(url, body).await
}

/// 快捷 DELETE 请求
///
/// # Example
///
/// ```ignore
/// let response = delete("https://api.example.com/users/1").await?;
/// ```
pub async fn delete(url: &str) -> Result<Response, HttpError> {
    default_client()?.delete(url).await
}

/// 快捷 PATCH 请求(JSON body)
///
/// # Example
///
/// ```ignore
/// let response = patch_json(
///     "https://api.example.com/users/1",
///     &partial_update
/// ).await?;
/// ```
pub async fn patch_json<T: Serialize>(url: &str, body: &T) -> Result<Response, HttpError> {
    default_client()?.patch_json(url, body).await
}

/// 快捷 HEAD 请求
///
/// # Example
///
/// ```ignore
/// let response = head("https://example.com/file.zip").await?;
/// let size = response.content_length();
/// ```
pub async fn head(url: &str) -> Result<Response, HttpError> {
    default_client()?.head(url).await
}

#[cfg(test)]
mod tests {
    // 便捷函数的测试需要网络,放在集成测试中
}