21个版本 (5个破坏性更新)
0.6.0 | 2022年11月29日 |
---|---|
0.5.2 | 2022年11月16日 |
0.4.1 | 2022年8月24日 |
0.3.2 | 2022年8月5日 |
0.1.4 | 2022年3月25日 |
#836 in HTTP服务器
每月92次下载
在 2 crates 中使用
69KB
1.5K SLoC
Resp Result
Web框架响应的帮助数据结构
为什么
- 当使用
Result
作为Web框架响应类型时,当Err(_)
时,通常不会是预期的500错误 - 使用非Result类型作为Web框架响应类型时,不能使用
?
,代码将充满if let
或match
这就是为什么我需要一个 RespResult
的原因,它可以
- 当它变成
RespResult::Err
时,控制响应代码或其他消息,而不仅仅是500
- 实现
Try
,因此可以使用友好的?
来简化代码
注意:因为
Try
尚未稳定,这个crate需要Nightly
rust
用法
安装
将 resp-result
添加到您的crate
[dependencies]
resp-result = "*"
功能标志
-
for-axum
:启用 axum 支持,这将实现IntoResponse
用于RespResult
-
extra-error
:在特性RespError
中启用额外错误消息 -
tracing
:启用使用 tracing 的记录器 -
axum-full
:等于for-axum
+extra-error
-
actix-full
:等于for-actix
+extra-error
-
nightly_try_v2
:为RespResult
实现Try
,使其可以使用?
,这将启用功能 try_trait_v2 并需要 Nightly rust 编译器
定义一个错误
RespResult<T,E>
要求 E
实现 RespError
例如
use resp_result::{RespError, RespResult};
use std::borrow::Cow;
use http::StatusCode;
pub struct PlainError(String);
impl RespError for PlainError{
fn log_message(&self) -> Cow<'_, str> {
Cow::Owned(format!("PlainError: {}", self.0))
}
fn resp_message(&self) -> Cow<'_, str> {
"PlainError".into()
}
fn http_code(&self) -> StatusCode {
StatusCode::BAD_REQUEST
}
type ExtraMessage = String;
fn extra_message(&self) -> Self::ExtraMessage {
self.0.clone()
}
}
/// this can be use as handler return type
type PlainRResult<T> = RespResult<T, PlainError>;
RespResult<T, E>
中 T
的边界
T
需要实现 Serialize
并具有 'static
生命周期
使用它
以下是一个使用 RespResult
的示例
use resp_result::{RespError, RespResult};
use std::borrow::Cow;
use http::StatusCode;
pub struct PlainError(String);
impl RespError for PlainError{
fn log_message(&self) -> Cow<'_, str> {
Cow::Owned(format!("PlainError: {}", self.0))
}
type ExtraMessage = String;
fn extra_message(&self) -> Self::ExtraMessage {
self.0.clone()
}
}
/// this can be use as handler return type
type PlainRResult<T> = RespResult<T, PlainError>;
pub async fn welcome_short_name(name: String) -> PlainRResult<String>{
if name.len() >= 8{
// you can using `?` just like the function that return `Result`
Err(PlainError("the name size great then 8".to_string()))?;
}
if name.len() >= 4 {
// `Result::Ok` can convert into `RespResult::Success` just using `into`
Ok(format!("welcome! {name} with size great then 4")).into()
}else{
// or just direct using `RespResult::ok`
RespResult::ok(format!("welcome! {name}"))
}
}
ExtraFlag 和 ExtraFlags
一般来说,RespResult::Success
总是生成状态码为 200 OK
的响应,并使用 serde_json
将正文序列化为 JSON。但有时我们希望返回一个 304 Not Modified
响应,正文为空,以告知客户端资源没有变化。为了支持上述使用情况,出现了 ExtraFlag
和 ExtraFlags
Extra Flag
额外的标志有 4 种不同的类型,可以对响应产生不同的影响
empty_body
:此标志将阻止RespResult
执行序列化到响应正文status
:此标志将覆盖响应的StatusCode
set-header
:此标志将提供或附加到响应头映射中remove-header
:此标志将从响应头映射中删除头
不同的额外标志可以使用 +
组合效果或使用 +=
添加效果
Extra Flags
额外的标志是一组额外的标志
FlagWrap
标志包装提供发送额外标志的包装器
在使用额外标志时,需要将返回类型从 RespResult<T, E>
更改为 RespResult<FlagWrap<T>, E>
以下示例将状态码更改为 404 Not Found
use resp_result::{RespError, RespResult, FlagWrap, ExtraFlag};
use std::borrow::Cow;
use http::StatusCode;
pub struct PlainError(String);
impl RespError for PlainError{
fn log_message(&self) -> Cow<'_, str> {
Cow::Owned(format!("PlainError: {}", self.0))
}
type ExtraMessage = String;
fn extra_message(&self) -> Self::ExtraMessage {
self.0.clone()
}
}
/// this can be use as handler return type
type PlainRResult<T> = RespResult<T, PlainError>;
pub async fn welcome_short_name(
name: String,
) -> PlainRResult<FlagWrap<String>>{
if name.len() >= 8{
RespResult::ok(
format!("welcome! {name} your name size is {}",name.len()))
// using `with_flags` to covert RespResult<T, E>
// to `RespResult<FlagWrap<T>, E>`
// using `()` for no extra flags
.with_flags(())
}else{
// suing `flag_ok` direct construct a flag with resp result
RespResult::flag_ok(
format!("Welcome! {name}"),
ExtraFlag::status(StatusCode::NOT_FOUND)
)
}
}
影响 RespResult
的行为
默认情况下,RespResult
将按如下方式序列化响应体:
{
"is-ok": true,
"error-message": "...",
"extra-msg": "...",
"body": null
}
可以通过使用 set_config
来设置全局配置以更改默认行为。
例如,通过配置,我们可以将响应体更改如下:
{
"status": "fail",
"reterror": 10001,
"message": "something wrong",
"body": null
}
依赖项
~2-14MB
~177K SLoC