Struct HttpError

Source
pub struct HttpError {
    pub http_status_code: StatusCode,
    pub public: Box<dyn DynSerialize + Send + Sync>,
    pub context: Option<String>,
}
Expand description

Self-sufficient container to both log an error and generate its HTTP response.

Error implements From<HttpError>, use ? and .into() in functions and closures to convert to the Error::Domain variant.

Note: HttpError convert to Error by converting first to DomainError.

§Examples

Domain errors that derive HttpError must implement From<&MyDomainError> for HttpError.

use explicit_error_http::{derive::HttpError, prelude::*, HttpError};

#[derive(HttpError, Debug)]
enum MyDomainError {
    Foo,
}

impl From<&MyDomainError> for HttpError {
    fn from(value: &MyDomainError) -> Self {
        match value {
            MyDomainError::Foo => HttpError::new(
                    StatusCode::BAD_REQUEST,
                    ProblemDetails::new()
                        .with_type(Uri::from_static("/errors/my-domain/foo"))
                        .with_title("Foo format incorrect.")
                ),
        }
    }
}

Domain errors cannot require to be extracted in either a struct or enum variant (eg: middleware errors). You can generate Error::Domain variant with an HttpError

use explicit_error_http::{Error, prelude::*, HttpError};

fn business_logic() -> Result<(), Error> {
    Err(HttpError::new(
        StatusCode::FORBIDDEN,
        ProblemDetails::new()
            .with_type(Uri::from_static("/errors/generic#forbidden"))
            .with_title("Forbidden."),
    ))?;
}

Usually to avoid boilerplate and having consistency in error responses web applications implement helpers for frequent http error codes.

use explicit_error_http::{prelude::*, HttpError, Error};

fn forbidden() -> HttpError {
    HttpError::new(
        StatusCode::FORBIDDEN,
        ProblemDetails::new()
            .with_type(Uri::from_static("/errors/generic#forbidden"))
            .with_title("Forbidden."),
    )
}

// context can be added by the caller to add information in log
fn business_logic() -> Result<(), Error> {
    Err(42).map_err(|e|
        forbidden().with_context(
            format!("Return a forbidden instead of 500 to avoid leaking implementation details: {e}")
    ))?;
}

Fields§

§http_status_code: StatusCode§public: Box<dyn DynSerialize + Send + Sync>§context: Option<String>

Implementations§

Source§

impl HttpError

Source

pub fn new<S: Serialize + 'static + Send + Sync>( http_status_code: StatusCode, public: S, ) -> Self

Generate an HttpError without a context. To add a context use with_context afterwards.

§Examples
fn forbidden() -> HttpError {
    HttpError::new(
        StatusCode::UNAUTHORIZED,
        ProblemDetails::new()
            .with_type(Uri::from_static("/errors/forbidden"))
            .with_title("Forbidden"),
    )
}
Source

pub fn with_context(self, context: impl Display) -> Self

Add a context to an HttpError, override if one was set. The context appears in display but not in the http response.

§Examples
fn check_authz() -> Result<()> {
    if !false {
        Err(forbidden().with_context("Some info to help debug"))?;
    }
    Ok(())
}

fn forbidden() -> HttpError {
    HttpError::new(
        StatusCode::UNAUTHORIZED,
        ProblemDetails::new()
            .with_type(Uri::from_static("/errors/forbidden"))
            .with_title("Forbidden"),
    )
}
Source

pub fn with_source<E: Error + 'static + Send + Sync>( self, error: E, ) -> DomainError

Add a source to an HttpError by converting it on the fly to a crate::DomainError

§Example
fn check() -> Result<()> {
    Err(sqlx::Error::RowNotFound).map_err(|e|
        HttpError::new(StatusCode::NOT_FOUND, "not found")
            .with_source(e))?;      
}

Trait Implementations§

Source§

impl Debug for HttpError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for HttpError

Source§

fn fmt<'s>(&'s self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<HttpError> for Error

Source§

fn from(value: HttpError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for HttpError

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for HttpError

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.