use actix_web::{
http::{header, StatusCode},
Either, HttpResponse, ResponseError,
};
use crate::{http, CowStr, Problem, Result};
impl ResponseError for Problem {
fn status_code(&self) -> StatusCode {
self.status()
}
fn error_response(&self) -> HttpResponse {
self.report_as_error();
HttpResponse::build(self.status())
.insert_header((header::CONTENT_TYPE, "application/problem+json"))
.json(self)
}
}
pub trait EitherExt<L, R> {
fn try_left(self, msg: impl Into<CowStr>) -> Result<L>;
fn try_right(self, msg: impl Into<CowStr>) -> Result<R>;
}
impl<L, R> EitherExt<L, R> for Either<L, R> {
#[track_caller]
fn try_left(self, msg: impl Into<CowStr>) -> Result<L> {
match self {
Either::Left(val) => Ok(val),
Either::Right(_) => Err(http::bad_request(msg)),
}
}
#[track_caller]
fn try_right(self, msg: impl Into<CowStr>) -> Result<R> {
match self {
Either::Left(_) => Err(http::bad_request(msg)),
Either::Right(val) => Ok(val),
}
}
}
#[cfg(test)]
mod tests {
use actix_web::body::MessageBody;
use super::*;
#[test]
fn test_response_error() {
let err = crate::http::failed_precondition();
assert_eq!(err.status_code(), err.status());
let resp = err.error_response();
assert_eq!(resp.status(), err.status());
assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap().as_bytes(),
b"application/problem+json"
);
let body = resp.into_body().try_into_bytes().unwrap();
assert_eq!(body, serde_json::to_vec(&err).unwrap());
}
#[test]
fn try_left_works() {
let a = Either::<i32, i32>::Left(1);
assert_eq!(1, a.try_left("a err").unwrap());
let b = Either::<i32, i32>::Right(2);
let err = b.try_left("b err").unwrap_err();
assert!(err.is::<http::BadRequest>());
assert_eq!("b err", err.details());
}
#[test]
fn try_right_works() {
let a = Either::<i32, i32>::Left(1);
let err = a.try_right("a err").unwrap_err();
assert!(err.is::<http::BadRequest>());
assert_eq!("a err", err.details());
let b = Either::<i32, i32>::Right(2);
assert_eq!(2, b.try_right("b err").unwrap());
}
}