35 个版本
| 0.0.14-beta.1 | 2024 年 5 月 6 日 |
|---|---|
| 0.0.13 | 2024 年 2 月 23 日 |
| 0.0.10 | 2024 年 1 月 25 日 |
| 0.0.7 | 2023 年 12 月 29 日 |
#866 in 网络编程
145KB
3.5K SLoC
API SDK
为 Rust 编写 HTTP API 客户端提供的一个易于使用的 API 工具包。
- 基于 reqwest 来处理 HTTP 请求
- 宏定义 API 和发送请求
- 以 JSON / XML / 表单 / 多部分的形式发送请求
- 通过 serde 解析响应
- 使用 serde_json 处理 JSON 响应
- 使用 quick-xml 处理 XML 响应
- 支持
X-Request-ID和X-Trace-ID/X-Span-ID - 更多定制能力
- 提供
UrlRewriter和DnsResolver来自定义 URL 和 API 端点 - 通过使用
ApiAuthenticator设置Authorization头 - 通过集成 reqwest-middleware 提供中间件
- 使用
MockServer模拟服务器响应
- 提供
- 变更日志
动机
当使用 reqwest 向服务器端发送 API 请求时,我们需要做一些常见的工作。包括设置认证信息、解析请求响应、处理异常、添加日志和跟踪信息等。
因此,我们通常开发一些辅助函数来实现上述功能。该 crate 的设计目的是简化这部分开发工作并提供一个通用的设计实现。
入门
安装
更新 Cargo.toml 以将此 crate 添加为依赖项。
[dependencies]
apisdk = { version = "0" }
此 crate 有几个功能
- uuid
- dns
- 安装
hickory-resolver(也称为trust-dns-resolver),并能够用它来进行 DNS 查询
- 安装
定义 API 结构体
要定义一个非常简单的 API,我们只需要几行代码。
use apisdk::{http_api, send, ApiResult};
// Define an API struct
#[http_api("https://www.example.com/api")]
#[derive(Debug, Clone)] // optional
pub struct MyApi;
// Response DTO
#[derive(serde::Deserialize)]
pub struct User {}
impl MyApi {
// Define a function for public use.
// It should return ApiResult<T>, which is an alias for Result<T, ApiError>.
pub async fn get_user(&self, user_id: u64) -> ApiResult<User> {
// Initiate a GET request with the URL path, and wait for the endpoint to be resolved.
let req = self.get(format!("/user/{}", user_id)).await?;
// Send the request to server, and parse it to result.
send!(req).await
}
}
调用 API
要使用 API,请按照以下步骤操作。
use apisdk::ApiResult;
async fn foo() -> ApiResult<()> {
// Initiate an API instance with default settings.
// Or use MyApi::builder().build() to generate a customized instance.
let api = MyApi::default();
// Invoke the function to execute HTTP request.
let user = api.get_user(1).await?;
Ok(())
}
关键点
http_api 和 api_method 宏
http_api- 声明一个结构体作为 API
#[http_api("https://api.site/base")]
api_method- (可选) 精炼 API 方法
创建 API 实例
我们可以使用 XxxApi::builder() 获取 ApiBuilder 的实例,并调用以下函数来定制 API 实例。
with_client- 设置
reqwest::ClientBuilder以定制客户端
- 设置
with_rewriter- 重写 HTTP URL
with_resolver- 自定义 DNS 查询
with_authenticator- 为每个请求设置凭证
with_initialiser&with_middleware- 支持所有
reqwest-middleware组件
- 支持所有
with_log- 在处理请求时启用/禁用日志
之后,我们应该调用 build() 来创建 API 实例。
对于非常简单的 API,我们可以使用 XxxApi::default() 来替换 XxxApi::builder().build()。
创建 HTTP 请求
API 实例提供一系列函数来协助创建 HTTP 请求。
- 通过 HTTP 方法创建
asyncfn request(method:Method,path:implAsRef<str>) -> ApiResult<RequestBuilder>
- 便利函数
asyncfn head(path:implAsRef<str>) -> ApiResult<RequestBuilder>asyncfn get(path:implAsRef<str>) -> ApiResult<RequestBuilder>asyncfn post(path:implAsRef<str>) -> ApiResult<RequestBuilder>asyncfn put(path:implAsRef<str>) -> ApiResult<RequestBuilder>asyncfn patch(path:implAsRef<str>) -> ApiResult<RequestBuilder>asyncfn delete(path:implAsRef<str>) -> ApiResult<RequestBuilder>asyncfn options(path:implAsRef<str>) -> ApiResult<RequestBuilder>asyncfn trace(path:implAsRef<str>) -> ApiResult<RequestBuilder>
我们还可以使用 API 实例的 core 字段来访问更多底层功能。
let api = XxxApi::default();
let req = api.core // an instance of apisdk::ApiCore
.rebase("http://different.host.com/api") // reset the BaseUrl
.build_request(Method::GET, "/path")?;
extends RequestBuilder
此包重新导出 RequestBuilder 从 reqwest-middleware,并提供了一些有用的扩展。我们可以使用 req.with_extension() 来应用这些扩展。
RequestId- 设置
X-Request-ID的值
- 设置
TraceId- 设置
X-Trace-ID和/或X-Span-ID的值
- 设置
MockServer- 模拟服务器响应
send 宏
send- 发送请求,不检测或处理有效载荷
send_json- 发送带有 JSON 有效载荷的请求
send_xml- 发送带有 XML 有效载荷的请求
send_form- 发送带有 urlencoded 表单或 multipart 表单的请求
send_multipart- 发送带有多部分表单的请求
这些宏支持以下表单。
// Form 1: send and parse response as JSON / XML
let _: Data = send!(req).await?;
// Form 2: send, drop response and return ApiResult<()>
send!(req, ()).await?;
// Form 3: send and return ResponseBody
let _ = send!(req, Body).await?;
// Form 4: send and parse JSON response to Data
let _: Data = send!(req, Json).await?;
// Form 5: send and parse XML response to Data
let _: Data = send!(req, Xml).await?;
// Form 6: send and parse Text response to Data by using FromStr trait
let _: Data = send!(req, Text).await?;
// Form 7: send and parse JSON response to Data
let _ = send!(req, Data).await?;
// Form 8: send and parse JSON response to Data
let _ = send!(req, Json<Data>).await?;
您可以检查 tests 获取更多示例。
依赖项
~11–24MB
~365K SLoC