14个版本
0.6.0 | 2024年5月5日 |
---|---|
0.5.3 | 2022年3月15日 |
0.5.2 | 2021年9月30日 |
#29 在 HTTP客户端
87,622 每月下载量
用于 12 个Crate (6个直接)
51KB
612 行
rustify
一个用于与HTTP API端点交互的Rust库
Rustify 是一个用Rust编写的库,它简化了搭建HTTP API的负担。它提供了一个 Endpoint
特征和一个宏助手,允许模板化各种远程端点。它还提供了异步和同步客户端,用于执行针对端点的请求,同时可以选择使用 Client
特征实现自定义客户端。
Rustify 提供了对请求序列化和响应反序列化的支持。还支持以字节形式存在的原始请求和响应。该库还包含了许多用于处理请求的助手,例如中间件支持和包装API响应。
安装
将 rustify 添加为 cargo.toml 中的依赖项
[dependencies]
rustify = "0.6.0"
rustify_derive = "0.5.2"
用法
基本用法
use rustify::{Client, Endpoint};
use rustify_derive::Endpoint;
// Defines an API endpoint at /test/path that takes no inputs and returns an
// empty response.
#[derive(Endpoint)]
#[endpoint(path = "test/path")]
struct Test {}
let endpoint = Test {};
let client = Client::default("http://api.com"); // Configures base address of http://api.com
let result = endpoint.exec(&client).await; // Sends GET request to http://api.com/test/path
assert!(result.is_ok());
请求体
use derive_builder::Builder;
use rustify::{Client, Endpoint};
use rustify_derive::Endpoint;
// Defines an API endpoint at /test/path/{name} that takes one input for
// creating the url and two inputs for building the request body. The content
// type of the request body defaults to JSON, however, it can be modified by
// passing the `request_type` parameter to the endpoint configuration.
//
// Note: The `#[endpoint(body)]` attribute tags are technically optional in the
// below example. If no `body` attribute is found anywhere then rustify defaults
// to serializing all "untagged" fields as part of the body. Fields can be opted
// out of this behavior by tagging them with #[endpoint(skip)].
#[derive(Builder, Endpoint)]
#[endpoint(path = "test/path/{self.name}", method = "POST", builder = "true")]
#[builder(setter(into))] // Improves the building process
struct Test {
#[endpoint(skip)] // This field shouldn't be serialized anywhere
pub name: String, // Used to create a dynamic URL
#[endpoint(body)] // Instructs rustify to serialize this field as part of the body
pub age: i32,
#[endpoint(body)]
pub role: String,
}
// Setting `builder` to true creates a `builder()` method on our struct that
// returns the TestBuilder type created by `derive_builder`.
let endpoint = Test::builder()
.name("jmgilman")
.age(42)
.role("CEO")
.build()
.unwrap();
let client = Client::default("http://api.com");
let result = endpoint.exec(&client).await; // Sends POST request to http://api.com/test/path/jmgilman
assert!(result.is_ok());
查询参数
use derive_builder::Builder;
use rustify::{Client, Endpoint};
use rustify_derive::Endpoint;
// Defines a similar API endpoint as in the previous example but adds an
// optional query parameter to the request. Additionally, this example opts to
// not specify the `#[endpoint(body)]` attributes to make use of the default
// behavior covered in the previous example.
#[derive(Builder, Endpoint)]
#[endpoint(path = "test/path/{self.name}", method = "POST", builder = "true")]
#[builder(setter(into, strip_option), default)] // Improves building process
struct Test {
#[endpoint(skip)]
pub name: String,
#[endpoint(query)]
pub scope: Option<String>, // Note: serialization is skipped when this field is None
pub age: i32, // Serialized into the request body
pub role: String, // Serialized into the request body
}
let endpoint = Test::builder()
.name("jmgilman")
.scope("global")
.age(42)
.role("CEO")
.build()
.unwrap();
let client = Client::default("http://api.com");
let result = endpoint.exec(&client).await; // Sends POST request to http://api.com/test/path/jmgilman?scope=global
assert!(result.is_ok());
响应
use rustify::{Client, Endpoint};
use rustify_derive::Endpoint;
// Defines an API endpoint at /test/path that takes a single byte array which
// will be used as the request body (no serialization occurs). The endpoint
// returns a `TestResponse` which contains the result of the operation.
#[derive(Endpoint)]
#[endpoint(path = "test/path", response = "TestResponse")]
struct Test {
#[endpoint(raw)] // Indicates this field contains the raw request body
pub file: Vec<u8>
}
#[derive(Deserialize)]
struct TestResponse {
pub success: bool,
}
let endpoint = Test {
file: b"contents".to_vec(),
};
let client = Client::default("http://api.com");
let result = endpoint.exec(&client).await;
assert!(result.is_ok());
let response = result.unwrap().parse().unwrap(); // Returns the parsed `TestResponse`
dbg!(response.success);
示例
您可以在 示例 目录中找到示例用法。它们可以使用 cargo 运行
cargo run --package rustify --example reqres1
cargo run --package rustify --example reqres2
vaultrs Crate 是基于 rustify 构建的,可以作为良好的参考。
功能
此Crate提供以下功能
blocking
:启用Client
的阻塞变体以及Endpoint
中的阻塞exec
函数。
错误处理
此Crate生成的所有错误都封装在由该Crate提供的 ClientError
枚举中。
测试
有关测试,请参阅 测试 目录。使用 cargo test
运行测试。
贡献
查看需要关注的问题,或提交您的问题,然后
- 将其分叉(https://github.com/jmgilman/rustify/fork)
- 创建您的功能分支(git checkout -b feature/fooBar)
- 提交您的更改(git commit -am '添加一些fooBar')
- 将更改推送到分支(git push origin feature/fooBar)
- 创建新的拉取请求
依赖
~6–21MB
~324K SLoC