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
use Debug;
use ;
use Request;
use *;
use ;
use URI;
/// Type alias for the `Outcome` of a `FromRequest` conversion.
pub type Outcome<S, E> = Outcome;
/// Trait used to derive an object from incoming request metadata.
///
/// An arbitrary number of types that implement this trait can appear as
/// parameters in a route handler, as illustrated below:
///
/// ```rust,ignore
/// #[get("/")]
/// fn index(a: A, b: B, c: C) -> ... { ... }
/// ```
///
/// In this example, `A`, `B`, and `C` can be any types that implements
/// `FromRequest`. There can be any number of `FromRequest` types in the
/// function signature. Note that unlike every other derived object in Rocket,
/// `FromRequest` parameter names do not need to be declared in the route
/// attribute.
///
/// Derivation of `FromRequest` arguments is always attemped in left-to-right
/// declaration order. In the example above, for instance, the order will be `a`
/// followed by `b` followed by `c`. If a deriviation fails, the following
/// aren't attempted.
///
/// # Outcomes
///
/// The returned [Outcome](/rocket/outcome/index.html) of a `from_request` call
/// determines how the incoming request will be processed.
///
/// * **Success**(S)
///
/// If the `Outcome` is `Success`, then the `Success` value will be used as
/// the value for the corresponding parameter. As long as all other parsed
/// types succeed, the request will be handled.
///
/// * **Failure**(Status, E)
///
/// If the `Outcome` is `Failure`, the request will fail with the given status
/// code and error. The designated error
/// [Catcher](/rocket/struct.Catcher.html) will be used to respond to the
/// request. Note that users can request types of `Result<S, E>` and
/// `Option<S>` to catch `Failure`s and retrieve the error value.
///
/// * **Forward**
///
/// If the `Outcome` is `Forward`, the request will be forwarded to the next
/// matching request. Note that users can request an `Option<S>` to catch
/// `Forward`s.
///
/// # Example
///
/// Imagine you're running an authenticated API service that requires that some
/// requests be sent along with a valid API key in a header field. You want to
/// ensure that the handlers corresponding to these requests don't get called
/// unless there is an API key in the request and the key is valid. The
/// following example implements this using an `APIKey` type and a `FromRequest`
/// implementation for that type. The `APIKey` type is then used in the
/// `senstive` handler.
///
/// ```rust
/// # #![feature(plugin)]
/// # #![plugin(rocket_codegen)]
/// # extern crate rocket;
/// #
/// use rocket::Outcome;
/// use rocket::http::Status;
/// use rocket::request::{self, Request, FromRequest};
///
/// struct APIKey(String);
///
/// /// Returns true if `key` is a valid API key string.
/// fn is_valid(key: &str) -> bool {
/// key == "valid_api_key"
/// }
///
/// impl<'a, 'r> FromRequest<'a, 'r> for APIKey {
/// type Error = ();
///
/// fn from_request(request: &'a Request<'r>) -> request::Outcome<APIKey, ()> {
/// let keys: Vec<_> = request.headers().get("x-api-key").collect();
/// if keys.len() != 1 {
/// return Outcome::Failure((Status::BadRequest, ()));
/// }
///
/// let key = keys[0];
/// if !is_valid(keys[0]) {
/// return Outcome::Forward(());
/// }
///
/// return Outcome::Success(APIKey(key.to_string()));
/// }
/// }
///
/// #[get("/sensitive")]
/// fn sensitive(key: APIKey) -> &'static str {
/// "Sensitive data."
/// }
///
/// # fn main() { }
/// ```