pub struct ProblemDetails<Ext = ()> {
    pub type: Option<ProblemType>,
    pub status: Option<StatusCode>,
    pub title: Option<String>,
    pub detail: Option<String>,
    pub instance: Option<Uri>,
    pub extensions: Ext,
}
Expand description

A RFC 9457 / RFC 7807 problem details object.

Creating problem details

You can create a new problem details from a given status code using ProblemDetails::from_status_code.

This will set the status field to the given status code, the title field to the canonical reason phrase of the status code, and the type field to none, which is equivalent to about:blank.

use http::StatusCode;
use problem_details::ProblemDetails;

let details = ProblemDetails::from_status_code(StatusCode::NOT_FOUND);

assert_eq!(details.status, Some(StatusCode::NOT_FOUND));
assert_eq!(details.title, Some("Not Found".to_string()));
assert_eq!(details.r#type.unwrap_or_default(), problem_details::ProblemType::default());

You can then use the builder pattern to add additional fields.

use http::{StatusCode, Uri};
use problem_details::ProblemDetails;

let details = ProblemDetails::from_status_code(StatusCode::NOT_FOUND)
   .with_type(Uri::from_static("example:type"))
   .with_title("There is something wrong");

assert_eq!(details.status, Some(StatusCode::NOT_FOUND));
assert_eq!(details.title, Some("There is something wrong".to_string()));
assert_eq!(details.r#type.unwrap_or_default(), Uri::from_static("example:type").into());

You can also create a new problem details object using ProblemDetails::new.

use http::Uri;
use problem_details::ProblemDetails;

let details = ProblemDetails::new()
  .with_type(Uri::from_static("example:type"))
  .with_title("There is something wrong");

assert_eq!(details.status, None);
assert_eq!(details.title, Some("There is something wrong".to_string()));
assert_eq!(details.r#type.unwrap_or_default(), Uri::from_static("example:type").into());

Extensions

To add extensions, you need to define a struct that holds the extension fields, and use this struct as the generic parameter for ProblemDetails<Ext>. Using with_extensions, the type is adjusted automatically for you.

Extension fields are flattened into the problem details object when serialized.

use problem_details::ProblemDetails;

struct MyExt {
    foo: String,
    bar: u32,
}

let details = ProblemDetails::new()
    .with_extensions(MyExt {
        foo: "Hello".to_string(),
        bar: 42,
    });

// details is of type ProblemDetails<MyExt>
let typecheck: ProblemDetails<MyExt> = details;

If you need dynamic extensions, you can use a HashMap as extensions object.

use std::collections::HashMap;
use problem_details::ProblemDetails;

let mut extensions = HashMap::<String, serde_json::Value>::new();
extensions.insert("foo".to_string(), serde_json::json!("Hello"));
extensions.insert("bar".to_string(), serde_json::json!(42));

let details = ProblemDetails::new()
   .with_extensions(extensions);

// details is of type ProblemDetails<HashMap<String, serde_json::Value>>
let typecheck: ProblemDetails<HashMap<String, serde_json::Value>> = details;

Fields§

§type: Option<ProblemType>

An optional uri describing the problem type.

See https://www.rfc-editor.org/rfc/rfc9457.html#name-type for more information.

§status: Option<StatusCode>

An optional status code for this problem.

See https://www.rfc-editor.org/rfc/rfc9457.html#name-status for more information.

§title: Option<String>

An optional human-readable title for this problem.

See https://www.rfc-editor.org/rfc/rfc9457.html#name-title for more information.

§detail: Option<String>

An optional human-readable description of this problem.

See https://www.rfc-editor.org/rfc/rfc9457.html#name-detail for more information.

§instance: Option<Uri>

An optional uri identifying the specific instance of this problem.

See https://www.rfc-editor.org/rfc/rfc9457.html#name-instance for more information.

§extensions: Ext

An object containing extensions to this problem details object.

Note that the extensions will be flattened into the resulting problem details representation.

See https://www.rfc-editor.org/rfc/rfc9457.html#name-extension-members for more information.

Implementations§

source§

impl ProblemDetails<()>

source

pub fn new() -> Self

Creates a new empty problem details object.

source

pub fn from_status_code(status: StatusCode) -> Self

Creates a new problem details object from a given status code.

This will set the status field to the given status code, the title field to the canonical reason phrase of the status code, and the type field to none, which is equivalent to about:blank.

source§

impl<Ext> ProblemDetails<Ext>

source

pub fn with_type(self, type: impl Into<ProblemType>) -> Self

Builder-style method that sets the type field of this problem details object.

source

pub fn with_status(self, status: impl Into<StatusCode>) -> Self

Builder-style method that sets the status field of this problem details object.

source

pub fn with_title(self, title: impl Into<String>) -> Self

Builder-style method that sets the title field of this problem details object.

source

pub fn with_detail(self, detail: impl Into<String>) -> Self

Builder-style method that sets the detail field of this problem details object.

source

pub fn with_instance(self, instance: impl Into<Uri>) -> Self

Builder-style method that sets the instance field of this problem details object.

source

pub fn with_extensions<NewExt>( self, extensions: NewExt ) -> ProblemDetails<NewExt>

Builder style method that sets the extensions field of this probelm details object.

Trait Implementations§

source§

impl<Ext: Clone> Clone for ProblemDetails<Ext>

source§

fn clone(&self) -> ProblemDetails<Ext>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<Ext: Debug> Debug for ProblemDetails<Ext>

source§

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

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

impl<Ext: Default> Default for ProblemDetails<Ext>

source§

fn default() -> ProblemDetails<Ext>

Returns the “default value” for a type. Read more
source§

impl<'de, Ext> Deserialize<'de> for ProblemDetails<Ext>
where Ext: Deserialize<'de>,

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl<Ext> Display for ProblemDetails<Ext>

source§

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

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

impl<Ext> Error for ProblemDetails<Ext>
where Ext: Debug,

1.30.0 · source§

fn source(&self) -> Option<&(dyn Error + 'static)>

The lower-level source of this error, if any. Read more
1.0.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type based access to context intended for error reports. Read more
source§

impl<Ext> From<JsonProblemDetails<Ext>> for ProblemDetails<Ext>

source§

fn from(value: JsonProblemDetails<Ext>) -> Self

Converts to this type from the input type.
source§

impl<Ext> From<ProblemDetails<Ext>> for JsonProblemDetails<Ext>

source§

fn from(value: ProblemDetails<Ext>) -> Self

Converts to this type from the input type.
source§

impl<Ext> From<ProblemDetails<Ext>> for XmlProblemDetails<Ext>

source§

fn from(value: ProblemDetails<Ext>) -> Self

Converts to this type from the input type.
source§

impl<Ext> From<XmlProblemDetails<Ext>> for ProblemDetails<Ext>

source§

fn from(value: XmlProblemDetails<Ext>) -> Self

Converts to this type from the input type.
source§

impl<Ext> IntoResponse for ProblemDetails<Ext>
where Ext: Serialize,

source§

fn into_response(self) -> Response

Create a response.
source§

impl<Ext> IntoResponse for ProblemDetails<Ext>
where Ext: Serialize + Send,

source§

fn into_response(self) -> Response

Consume itself and return Response.
source§

fn with_header<K, V>(self, key: K, value: V) -> WithHeader<Self>
where K: TryInto<HeaderName>, V: TryInto<HeaderValue>, Self: Sized,

Wrap an impl IntoResponse to add a header. Read more
source§

fn with_content_type<V>(self, content_type: V) -> WithContentType<Self>
where V: TryInto<HeaderValue>, Self: Sized,

Wrap an impl IntoResponse to with a new content type. Read more
source§

fn with_status(self, status: StatusCode) -> WithStatus<Self>
where Self: Sized,

Wrap an impl IntoResponse to set a status code. Read more
source§

fn with_body(self, body: impl Into<Body>) -> WithBody<Self>
where Self: Sized,

Wrap an impl IntoResponse to set a body. Read more
source§

impl<Ext: PartialEq> PartialEq for ProblemDetails<Ext>

source§

fn eq(&self, other: &ProblemDetails<Ext>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

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

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<Ext> ResponseError for ProblemDetails<Ext>
where Ext: Serialize + Clone + Send,

source§

fn status(&self) -> StatusCode

The status code of this error.
source§

fn as_response(&self) -> Response

Convert this error to a HTTP response.
source§

impl<Ext> Serialize for ProblemDetails<Ext>
where Ext: Serialize,

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
source§

impl<Ext: Eq> Eq for ProblemDetails<Ext>

source§

impl<Ext> StructuralEq for ProblemDetails<Ext>

source§

impl<Ext> StructuralPartialEq for ProblemDetails<Ext>

Auto Trait Implementations§

§

impl<Ext> RefUnwindSafe for ProblemDetails<Ext>
where Ext: RefUnwindSafe,

§

impl<Ext> Send for ProblemDetails<Ext>
where Ext: Send,

§

impl<Ext> Sync for ProblemDetails<Ext>
where Ext: Sync,

§

impl<Ext> Unpin for ProblemDetails<Ext>
where Ext: Unpin,

§

impl<Ext> UnwindSafe for ProblemDetails<Ext>
where Ext: UnwindSafe,

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
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FromRef<T> for T
where T: Clone,

§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
source§

impl<T, S> Handler<IntoResponseHandler, S> for T
where T: IntoResponse + Clone + Send + 'static,

§

type Future = Ready<Response<Body>>

The type of future calling this handler returns.
source§

fn call( self, _req: Request<Body>, _state: S ) -> <T as Handler<IntoResponseHandler, S>>::Future

Call the handler with the given request.
source§

fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>
where L: Layer<HandlerService<Self, T, S>> + Clone, <L as Layer<HandlerService<Self, T, S>>>::Service: Service<Request<Body>>,

Apply a [tower::Layer] to the handler. Read more
source§

fn with_state(self, state: S) -> HandlerService<Self, T, S>

Convert the handler into a [Service] by providing the state
source§

impl<H, T> HandlerWithoutStateExt<T> for H
where H: Handler<T, ()>,

source§

fn into_service(self) -> HandlerService<H, T, ()>

Convert the handler into a [Service] and no state.
source§

fn into_make_service(self) -> IntoMakeService<HandlerService<H, T, ()>>

Convert the handler into a MakeService and no state. Read more
§

impl<T> Instrument for T

§

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

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

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> IntoResult<T> for T
where T: IntoResponse,

source§

fn into_result(self) -> Result<T, Error>

Consumes this value returns a poem::Result<T>.
source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

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

source§

default 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>,

§

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>,

§

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.
§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,