我有一个函数,当我想抛出错误时,它会返回用Result包裹的 struct AppError.

在下面,我试图抛出401(未授权)并显示"无效凭据"消息,但每次打开代码时,我都必须写.ok_or()才能处理这个问题.

pub async fn refresh_uses_session(
    State(app_state): State<AppState>,
    cookie_jar: CookieJar,
) -> Result<Response, AppError> {
    let refresh_token_cookie = cookie_jar
        .get("refresh_token")
        .ok_or((StatusCode::UNAUTHORIZED, "Invalid Credentials").into_app_error())?;

    let cookie_expiration_time = refresh_token_cookie
        .expires()
        .ok_or((StatusCode::UNAUTHORIZED, "Invalid Credentials").into_app_error())?
        .datetime()
        .ok_or((StatusCode::UNAUTHORIZED, "Invalid Credentials").into_app_error())?;

    if cookie_expiration_time <= OffsetDateTime::now_utc() {
        return Err((StatusCode::UNAUTHORIZED, "Invalid Credentials").into_app_error());
    }

    //…
}

有没有办法在不更改返回类型或助手函数的情况下减少.ok_or()次调用?

推荐答案

使用Option API,您应该能够使用and_thenfilter函数将可选链不断滚动为单个值.

下面(简化得多)的例子应该说明我的意思:

struct Cookie {
    expires: Option<String>,
}

struct CookieJar {
    refresh_token: Option<Cookie>,
}

fn main() {
    let result = test_function();
    println!("{:?}", result);
}


fn test_function() -> Result<String, String> {
    let cookie_jar = CookieJar { refresh_token: Some(Cookie { expires: None }) };

    cookie_jar
        .refresh_token
        .and_then(|cookie| {cookie.expires})
        .filter(|expiration| {expiration == "2024-04-28"})
        .ok_or("My error message".to_string())
}

Playground

Rust相关问答推荐

为什么单元类型(空元组)实现了`Extend`trait?

Rust kill std::processs::child

如何使用字符串迭代器执行查找?

什么时候铁 rust FFI边界上的panic 是未定义的行为?

如何用Axum/Tower压缩Html内容?

如何在Rust中将选项<;选项<;字符串>;转换为选项<;选项&;str>;?

如何go 除多余的(0..)在迭代中,当它不被使用时?

将serde_json读入`VEC<;T&>;`( rust 色)时出现问题

确保参数是编译时定义的字符串文字

要求类型参数有特定的大小?

Rust 中的静态引用

使用启用优化的 alloc 会导致非法指令崩溃

Rust Option 的空显式泛型参数

在Rust中实现Trie数据 struct 的更好方式

如何在 Rust 中将 UTF-8 十六进制值转换为 char?

如何解析 Rust 中的 yaml 条件字段?

是否有适当的方法在参考 1D 中转换 2D 数组

在空表达式语句中移动的值

当 `T` 没有实现 `Debug` 时替代 `unwrap()`

为什么我不能为 Display+Debug 的泛型类型实现 std::error::Error 但有一个不是泛型参数的类型?