Struct HttpError

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

Self-sufficient container to both log an error and generate its HTTP response. Regarding the web framework you use, its shape can be different.

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>§context: Option<String>

Implementations§

Source§

impl HttpError

Source

pub fn new<S: Serialize + 'static>( 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"),
    )
}

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 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> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> Same for T

Source§

type Output = T

Should always be Self
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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,