1个不稳定版本
0.5.3 | 2023年4月22日 |
---|
#344 in HTTP客户端
在bangumi中使用
40KB
573 行
rustified
由于维护不足,rustified是rustify的分支。
一个用于与HTTP API端点交互的Rust库
rustified是一个用Rust编写的库,简化了搭建HTTP API的负担。它提供了一个Endpoint
trait以及一个宏助手,允许模板化各种远程端点。提供了异步和同步客户端来执行针对端点的请求,并可选择实现自定义客户端,使用Client
trait。
rustified支持请求序列化和响应反序列化。还支持以字节形式表示的原始请求和响应。该库还包含许多处理请求的助手,如中间件支持和包装API响应。
安装
将rustified添加到您的cargo.toml作为依赖项
[dependencies]
rustified = "0.5.3"
rustified_derive = "0.5.3"
使用方法
基本使用
use rustified::{Client, Endpoint};
use rustified_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 rustified::{Client, Endpoint};
use rustified_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 rustified 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 rustified 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("George-Miao")
.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/George-Miao
assert!(result.is_ok());
查询参数
use derive_builder::Builder;
use rustified::{Client, Endpoint};
use rustified_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("George-Miao")
.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/George-Miao?scope=global
assert!(result.is_ok());
响应
use rustified::{Client, Endpoint};
use rustified_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 rustified --example reqres1
cargo run --package rustified --example reqres2
基于rustify构建的vaultrs crate是一个很好的参考。
功能
此crate提供以下功能
blocking
:启用Client
的阻塞变体以及Endpoint
中的阻塞exec
函数。
错误处理
本crate产生的所有错误都封装在crate提供的ClientError
枚举中。
测试
有关测试,请参阅测试目录。使用cargo test
运行测试。
依赖项
~6–24MB
~351K SLoC