I have a function that returns a struct AppError
wrapped with Result
when I want to throw an error.
Below I am trying to throw 401(Unauthorized) with the message "Invalid Credentials" but every time I unwrap the code I have to write .ok_or()
to handle this.
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());
}
//…
}
Is there any way to reduce the .ok_or()
calls without changing the return type or helper function?
Using the Option
API you should be able to use the and_then
and filter
functions to keep rolling your optional chain into a single value.
The following (much simplified) example should illustrate what I mean:
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())
}