Crates.io | problem_details |
lib.rs | problem_details |
version | 0.6.0 |
source | src |
created_at | 2023-10-08 19:22:16.571152 |
updated_at | 2024-01-10 19:45:20.010413 |
description | RFC 9457 / RFC 7807 problem details for HTTP APIs. |
homepage | |
repository | https://github.com/frenetisch-applaudierend/problem-details-rs |
max_upload_size | |
id | 997404 |
size | 77,862 |
RFC 9457 / RFC 7807 problem details for HTTP APIs.
This crate provides the ProblemDetails
struct which implements the RFC 9457 / RFC 7807
problem details specification.
It supports serializing and deserializing problem details using JSON, and provides integration with the axum (0.7) and poem (2.0) web frameworks.
The following example shows how to create a problem details object that produces the example JSON from the RFC.
use http::Uri;
use problem_details::ProblemDetails;
#[derive(serde::Serialize)]
struct OutOfCreditExt {
balance: u32,
accounts: Vec<String>,
}
let details = ProblemDetails::new()
.with_type(Uri::from_static("https://example.com/probs/out-of-credit"))
.with_title("You do not have enough credit.")
.with_detail("Your current balance is 30, but that costs 50.")
.with_instance(Uri::from_static("/account/12345/msgs/abc"))
.with_extensions(OutOfCreditExt {
balance: 30,
accounts: vec![
"/account/12345".to_string(),
"/account/67890".to_string(),
],
});
let json = serde_json::to_value(&details).unwrap();
assert_eq!(json, serde_json::json!({
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc",
"balance": 30,
"accounts": [
"/account/12345",
"/account/67890"
]
}));
Extensions can be added
to the problem details object using the with_extensions
method. The extensions are passed using a struct defining the extension fields.
During serialization, the extension fields are flattened into the problem details object.
use problem_details::ProblemDetails;
#[derive(serde::Serialize, serde::Deserialize)]
struct MyExt {
foo: String,
bar: u32,
}
let details = ProblemDetails::new()
.with_title("Extensions test")
.with_extensions(MyExt {
foo: "Hello".to_string(),
bar: 42,
});
let json = serde_json::to_value(&details).unwrap();
assert_eq!(json, serde_json::json!({
"title": "Extensions test",
"foo": "Hello",
"bar": 42
}));
To deserialize with extensions, provide the extensions type as the generic
parameter to the ProblemDetails
struct.
let details: ProblemDetails<MyExt> = serde_json::from_str(json).unwrap();
If you need dynamic extensions, you can use a HashMap
as extensions object.
ProblemDetails
struct (enabled by default)serde
)serde
)axum
web framework, enabling to return ProblemDetails
as responses.poem
web framework, enabling to return ProblemDetails
as responses and errors.This crate is not fully compliant with RFC 9457, because it fails to deserialize JSON values containing properties with incorrect types (required by Chapter 3.1 of the RFC).
Licensed under either of
at your option.