caller 0.2.0

A WebApi Caller
Documentation

Caller For Rust

一个灵活、可配置的 Web API 请求库,基于 Rust 开发,支持通过 JSON 配置文件管理多个 API 端点。

特性

  • 🚀 异步调用:基于 Tokio 异步运行时,支持高并发请求
  • 配置化管理:通过 JSON 配置文件定义 API 端点
  • 🔄 热重载:支持配置文件热重载,无需重启即可更新配置
  • 🔐 认证支持:内置多种认证机制(header、query、basic auth)
  • 📊 结果解析:强大的 JSON 结果解析,支持深度路径访问
  • 🛡️ 错误处理:完善的错误类型和错误处理机制
  • 🧪 测试覆盖:内置全面的单元测试和集成测试
  • 🏗️ 模块化架构:清晰的分层架构,易于扩展和维护

架构设计

项目结构

src/
├── core/          # 核心业务逻辑
│   ├── context.rs # 调用上下文管理
│   └── constants.rs # 常量定义
├── domain/        # 领域模型
│   ├── api_item.rs      # API 项目定义
│   ├── api_result.rs    # API 响应结果
│   ├── authorization.rs # 认证相关
│   ├── caller_config.rs # 调用配置
│   └── service_item.rs  # 服务项目定义
├── config/        # 配置管理
│   └── config_loader.rs # 配置加载器
├── infra/         # 基础设施层
│   └── http.rs     # HTTP 客户端封装
└── shared/        # 共享模块
    └── error.rs    # 错误定义

工作流程

  1. 配置加载:从 JSON 文件加载 API 配置
  2. 上下文管理:管理调用上下文和中间件
  3. HTTP 调用:构造和发送 HTTP 请求
  4. 结果处理:解析和格式化响应结果

快速开始

添加依赖

[dependencies]

caller = "0.1.0"

tokio = { version = "1.0", features = ["full"] }

基本使用

use caller::call;
use std::collections::HashMap;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 简单调用
    let result = call("JP.list", None).await?;

    // 解析结果
    println!("Status: {}", result.status_code);
    println!("Raw response: {}", result.raw);

    // 获取特定字段
    if let Some(first_title) = result.get_as_str("0.title") {
        println!("First post title: {}", first_title);
    }

    // 带参数调用
    let params = HashMap::from([
        ("post_id".to_string(), "1".to_string()),
        ("userId".to_string(), "1".to_string()),
    ]);
    let result = call("JP.get", Some(params)).await?;

    Ok(())
}

配置文件

创建 caller.json 配置文件来定义 API 端点:

{
  "Authorizations": [
    {
      "Name": "BearerToken",
      "HeaderName": "Authorization",
      "Type": "Bearer",
      "Token": "your-token-here"
    }
  ],
  "ServiceItems": [
    {
      "ApiName": "weibo",
      "BaseUrl": "https://weibo.com/ajax",
      "ApiItems": [
        {
          "Method": "hot",
          "Url": "/side/hotSearch",
          "HttpMethod": "GET",
          "ParamType": "query",
          "Description": "获取微博热搜",
          "Timeout": 5000,
          "NeedCache": true,
          "CacheTime": 300
        }
      ]
    },
    {
      "ApiName": "JP",
      "BaseUrl": "https://jsonplaceholder.typicode.com",
      "ApiItems": [
        {
          "Method": "get",
          "Url": "/posts/{post_id}",
          "HttpMethod": "GET",
          "ParamType": "path"
        },
        {
          "Method": "create",
          "Url": "/posts",
          "HttpMethod": "POST",
          "ParamType": "json",
          "ContentType": "application/json",
          "AuthorizationType": "BearerToken"
        }
      ]
    }
  ]
}

参数类型说明

参数类型 描述 示例
none 无参数 /posts
query 查询参数 /posts?userId=1&id=1
path 路径参数 /posts/1
json JSON 请求体 {"title": "Hello", "body": "World"}
path,json 路径参数 + JSON 体 /posts/1 + {"title": "Updated"}

API 参考

主要类型

ApiResult

pub struct ApiResult {
    pub status_code: StatusCode,
    pub raw: String,
    pub j_obj: Value,
}

CallerError

pub enum CallerError {
    ConfigError(String),
    HttpError(reqwest::Error),
    JsonError(String),
    ServiceNotFound(String),
    MethodNotFound(String),
    ParamMissing(String),
    AuthenticationError(String),
}

核心方法

api_result.get_as_str(key: &str) -> Option<&str>

获取字符串类型的值,支持深度路径如 "0.title"

api_result.get_as_i64(key: &str) -> Option<i64>

获取整数值

api_result.get_as_bool(key: &str) -> Option<bool>

获取布尔值

api_result.get(key: &str) -> Option<&Value>

获取原生 JSON 值

配置热重载

Caller 支持配置文件热重载,无需重启程序即可更新 API 配置。

use caller::{call, init_config, reload_config, watch_config, stop_watch_config, is_watching_config};

// 初始化配置(通常在应用启动时调用)
init_config()?;

// 手动重新加载配置
reload_config()?;

// 启动文件监听,自动检测配置文件变更
// 使用默认 500ms 防抖时间
watch_config()?;

// 或使用自定义防抖时间(最小 100ms)
use std::time::Duration;
watch_config_with_debounce(Duration::from_millis(1000))?;

// 检查是否正在监听
if is_watching_config() {
    println!("配置文件正在被监听");
}

// 停止监听
stop_watch_config();

公共 API

call(method: &str, params: Option<HashMap<String, String>>) -> Result<ApiResult, CallerError>

use caller::call;
use std::collections::HashMap;

// 无参数调用
let result = call("JP.list", None).await?;

// 带参数调用
let params = HashMap::from([
    ("post_id".to_string(), "1".to_string()),
]);
let result = call("JP.get", Some(params)).await?;

测试

运行所有测试:

cargo test

运行特定测试:

cargo test test_call_list_posts

构建和发布

# 构建

cargo build


# 运行示例

cargo run --example basic_usage


# 格式化代码

cargo fmt


# 检查代码

cargo check

贡献指南

  1. Fork 本仓库
  2. 创建特性分支 (git checkout -b feature/amazing-feature)
  3. 提交更改 (git commit -m 'Add amazing feature')
  4. 推送到分支 (git push origin feature/amazing-feature)
  5. 创建 Pull Request

许可证

本项目采用 MIT 许可证 - 查看 LICENSE 文件了解详情

更新日志

v0.1.0

  • 初始版本发布
  • 支持基于配置文件的 API 调用
  • 支持多种 HTTP 方法和参数类型
  • 内置认证和缓存支持
  • 完善的错误处理
  • 全面的测试覆盖