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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
//! Rejection types.
//!
//! This module contains types that are commonly used as the `E` error type in functions that
//! handle requests and responses that return `Result<T, E>` throughout the framework. These
//! include functions to deserialize incoming requests and serialize outgoing responses.
//!
//! All types end with `Rejection`. There are two types:
//!
//! 1. [`RequestRejection`]s are used when the framework fails to deserialize the request into the
//! corresponding operation input.
//! 2. [`ResponseRejection`]s are used when the framework fails to serialize the operation
//! output into a response.
//!
//! They are called _rejection_ types and not _error_ types to signal that the input was _rejected_
//! (as opposed to it causing a recoverable error that would need to be handled, or an
//! unrecoverable error). For example, a [`RequestRejection`] simply means that the request was
//! rejected; there isn't really anything wrong with the service itself that the service
//! implementer would need to handle.
//!
//! Rejection types are an _internal_ detail about the framework: they can be added, removed, and
//! modified at any time without causing breaking changes. They are not surfaced to clients or the
//! service implementer in any way (including this documentation): indeed, they can't be converted
//! into responses. They serve as a mechanism to keep track of all the possible errors that can
//! occur when processing a request or a response, in far more detail than what AWS protocols need
//! to. This is why they are so granular: other (possibly protocol-specific) error types (like
//! [`crate::protocol::rest_json_1::runtime_error::RuntimeError`]) can "group" them when exposing
//! errors to clients while the framework does not need to sacrifice fidelity in private error
//! handling routines, and future-proofing itself at the same time (for example, we might want to
//! record metrics about rejection types).
//!
//! Rejection types implement [`std::error::Error`], and some take in type-erased boxed errors
//! (`crate::Error`) to represent their underlying causes, so they can be composed with other types
//! that take in (possibly type-erased) [`std::error::Error`]s, like
//! [`crate::protocol::rest_json_1::runtime_error::RuntimeError`], thus allowing us to represent the
//! full error chain.
//!
//! This module hosts rejection types _specific_ to the [`crate::protocol::rest_json_1`] protocol, but
//! the paragraphs above apply to _all_ protocol-specific rejection types.
//!
//! Similarly, rejection type variants are exhaustively documented solely in this module if they have
//! direct counterparts in other protocols. This is to avoid documentation getting out of date.
//!
//! Consult `crate::protocol::$protocolName::rejection` for rejection types for other protocols.
use crateMissingContentTypeReason;
use HttpError;
use TryFromIntError;
use Error;
/// Errors that can occur when serializing the operation output provided by the service implementer
/// into an HTTP response.
/// Errors that can occur when deserializing an HTTP request into an _operation input_, the input
/// that is passed as the first argument to operation handlers.
///
/// This type allows us to easily keep track of all the possible errors that can occur in the
/// lifecycle of an incoming HTTP request.
///
/// Many inner code-generated and runtime deserialization functions use this as their error type,
/// when they can only instantiate a subset of the variants (most likely a single one). This is a
/// deliberate design choice to keep code generation simple. After all, this type is an inner
/// detail of the framework the service implementer does not interact with.
///
/// If a variant takes in a value, it represents the underlying cause of the error.
///
/// The variants are _roughly_ sorted in the order in which the HTTP request is processed.
// Consider a conversion between `T` and `U` followed by a bubbling up of the conversion error
// through `Result<_, RequestRejection>`. This [`From`] implementation accomodates the special case
// where `T` and `U` are equal, in such cases `T`/`U` a enjoy `TryFrom<T>` with
// `Err = std::convert::Infallible`.
//
// Note that when `!` stabilizes `std::convert::Infallible` will become an alias for `!` and there
// will be a blanket `impl From<!> for T`. This will remove the need for this implementation.
//
// More details on this can be found in the following links:
// - https://doc.rust-lang.org/std/primitive.never.html
// - https://doc.rust-lang.org/std/convert/enum.Infallible.html#future-compatibility
// Conversion from crate::Error is needed for custom body types and testing scenarios.
// When using BoxBody or custom body implementations, errors are crate::Error, not hyper::Error.
// These converters are solely to make code-generation simpler. They convert from a specific error
// type (from a runtime/third-party crate or the standard library) into a variant of the
// [`crate::rejection::RequestRejection`] enum holding the type-erased boxed [`crate::Error`]
// type. Generated functions that use [crate::rejection::RequestRejection] can thus use `?` to
// bubble up instead of having to sprinkle things like [`Result::map_err`] everywhere.
// Hyper's HTTP server provides requests with `hyper::body::Incoming`, which has error type
// `hyper::Error`. During request deserialization (FromRequest), body operations can produce
// this error, so we need this conversion to handle it within the framework.
convert_to_request_rejection!;
// Useful in general, but it also required in order to accept Lambda HTTP requests using
// `Router<lambda_http::Body>` since `lambda_http::Error` is a type alias for `Box<dyn Error + ..>`.
convert_to_request_rejection!;