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
//! Tower layer for error response rendering with content negotiation.
use ;
use Layer;
/// Tower layer that wraps services to automatically render errors as HTTP responses.
///
/// This layer intercepts errors from your service and converts them into properly
/// formatted HTTP responses based on the client's `Accept` header. It supports
/// JSON, GraphQL, HTML, and plain text formats.
///
/// # Examples
///
/// ## Basic Usage
///
/// ```rust
/// use apollo_errors::tower_http::ErrorLayer;
/// use tower::ServiceBuilder;
/// # use tower::service_fn;
/// # use http::{Request, Response};
///
/// let service = ServiceBuilder::new()
/// .layer(ErrorLayer::new())
/// .service(service_fn(|_req: Request<String>| async {
/// Ok::<_, Box<dyn std::error::Error>>(Response::new("OK"))
/// }));
/// ```
///
/// ## With Custom Configuration
///
/// ```rust
/// use apollo_errors::tower_http::{ErrorLayer, NegotiationConfig, Renderer};
/// use tower::ServiceBuilder;
/// # use tower::service_fn;
/// # use http::{Request, Response};
///
/// let config = NegotiationConfig::new()
/// .with_mapping("application/vnd.api+json", Renderer::Json)
/// .with_fallback(Renderer::Html);
///
/// let service = ServiceBuilder::new()
/// .layer(ErrorLayer::with_config(config))
/// .service(service_fn(|_req: Request<String>| async {
/// Ok::<_, Box<dyn std::error::Error>>(Response::new("OK"))
/// }));
/// ```
///
/// ## With Custom Error Types
///
/// ```rust
/// use apollo_errors::{Error, miette::Diagnostic, tower_http::ErrorLayer};
/// use tower::ServiceBuilder;
/// # use tower::service_fn;
/// # use http::{Request, Response};
///
/// #[derive(Debug, Error, Diagnostic)]
/// pub enum MyError {
/// #[error("Something went wrong")]
/// #[diagnostic(code(my::error))]
/// BadThing,
/// }
///
/// async fn handler(_req: Request<String>) -> Result<Response<String>, MyError> {
/// Err(MyError::BadThing)
/// }
///
/// # async fn example() {
/// let service = ServiceBuilder::new()
/// .layer(ErrorLayer::new())
/// .service_fn(handler);
/// # }
/// ```