1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! RFC 9457 / RFC 7807 problem details for HTTP APIs.
//!
//! This crate can be used to represent a problem details
//! object as defined in RFC 9457 (which obsoletes RFC 7807).
//!
//! The [`ProblemDetails`] struct includes the standard fields
//! ([`type`](ProblemDetails::type), [`status`](ProblemDetails::status),
//! [`title`](ProblemDetails::title), [`detail`](ProblemDetails::detail),
//! [`instance`](ProblemDetails::instance)),
//! as well as type-safe custom extensions.
//!
//! # 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`](ProblemDetails::with_extensions), the type is adjusted
//! automatically for you.
//!
//! Extension fields are flattened into the problem details object when serialized.
//!
//! ```rust
//! 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`](std::collections::HashMap)
//! as extensions object.
//!
//! ```rust
//! 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;
//! ```
//!
//! # Example
//!
//! The following example shows how to create a problem details object that produces
//! the [example JSON from the RFC](https://www.rfc-editor.org/rfc/rfc9457.pdf#name-the-problem-details-json-ob).
//!
//! ```rust
//! 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"
//! ]
//! }));
//! ```
//!
//! # Features
//!
//! - **serde**: Enables serde support for the `ProblemDetails` struct (_enabled by default_)
//! - **json**: Enables serialization to JSON when using web framework integrations (_enabled by default, implies `serde`_)
//! - **xml**: Enables serialization to XML when using web framework integrations (_implies `serde`_)
//! - **axum**: Enables integration with the [`axum`](https://crates.io/crates/axum) web framework, allowing to
//! return `ProblemDetails` as responses.
//! - **poem**: Enables integration with the [`poem`](https://crates.io/crates/poem) web framework, allowing to
//! return `ProblemDetails` as responses and errors.
//! - **actix**: Enables integration with the [`actix-web`](https://crates.io/crates/actix-web) web framework, allowing to
//! return `ProblemDetails` as errors.
//! - **utoipa**: Enables integration with the [`utoipa`](https://crates.io/crates/utoipa) OpenAPI schema generator,
//! allowing to use `ProblemDetails` as response type.
//!
//! # Caveats
//!
//! This crate is not fully compliant with the RFC, because it fails to deserialize
//! JSON values containing properties with incorrect types (required by
//! [Chapter 3.1 of the RFC](https://www.rfc-editor.org/rfc/rfc9457.pdf#name-members-of-a-problem-detail)).
pub use *;
pub use *;
// Axum Support
// Poem Support
// Actix support
// Serde related extensions for http