1 use std::rc::Rc;
2 use std::cell::{Cell, RefCell};
3 use std::net::{IpAddr, SocketAddr};
4 use std::fmt;
5 use std::str;
6 
7 use yansi::Paint;
8 use state::{Container, Storage};
9 
10 use crate::request::{FromParam, FromSegments, FromRequest, Outcome};
11 use crate::request::{FromFormValue, FormItems, FormItem};
12 
13 use crate::rocket::Rocket;
14 use crate::router::Route;
15 use crate::config::{Config, Limits};
16 use crate::http::{hyper, uri::{Origin, Segments}};
17 use crate::http::{Method, Header, HeaderMap, Cookies};
18 use crate::http::{RawStr, ContentType, Accept, MediaType};
19 use crate::http::private::{Indexed, SmallVec, CookieJar};
20 
21 type Indices = (usize, usize);
22 
23 /// The type of an incoming web request.
24 ///
25 /// This should be used sparingly in Rocket applications. In particular, it
26 /// should likely only be used when writing [`FromRequest`] implementations. It
27 /// contains all of the information for a given web request except for the body
28 /// data. This includes the HTTP method, URI, cookies, headers, and more.
29 #[derive(Clone)]
30 pub struct Request<'r> {
31     method: Cell<Method>,
32     uri: Origin<'r>,
33     headers: HeaderMap<'r>,
34     remote: Option<SocketAddr>,
35     pub(crate) state: RequestState<'r>,
36 }
37 
38 #[derive(Clone)]
39 pub(crate) struct RequestState<'r> {
40     pub config: &'r Config,
41     pub managed: &'r Container,
42     pub path_segments: SmallVec<[Indices; 12]>,
43     pub query_items: Option<SmallVec<[IndexedFormItem; 6]>>,
44     pub route: Cell<Option<&'r Route>>,
45     pub cookies: RefCell<CookieJar>,
46     pub accept: Storage<Option<Accept>>,
47     pub content_type: Storage<Option<ContentType>>,
48     pub cache: Rc<Container>,
49 }
50 
51 #[derive(Clone)]
52 pub(crate) struct IndexedFormItem {
53     raw: Indices,
54     key: Indices,
55     value: Indices
56 }
57 
58 impl<'r> Request<'r> {
59     /// Create a new `Request` with the given `method` and `uri`.
60     #[inline(always)]
new<'s: 'r>( rocket: &'r Rocket, method: Method, uri: Origin<'s> ) -> Request<'r>61     pub(crate) fn new<'s: 'r>(
62         rocket: &'r Rocket,
63         method: Method,
64         uri: Origin<'s>
65     ) -> Request<'r> {
66         let mut request = Request {
67             method: Cell::new(method),
68             uri: uri,
69             headers: HeaderMap::new(),
70             remote: None,
71             state: RequestState {
72                 path_segments: SmallVec::new(),
73                 query_items: None,
74                 config: &rocket.config,
75                 managed: &rocket.state,
76                 route: Cell::new(None),
77                 cookies: RefCell::new(CookieJar::new()),
78                 accept: Storage::new(),
79                 content_type: Storage::new(),
80                 cache: Rc::new(Container::new()),
81             }
82         };
83 
84         request.update_cached_uri_info();
85         request
86     }
87 
88     /// Retrieve the method from `self`.
89     ///
90     /// # Example
91     ///
92     /// ```rust
93     /// # use rocket::Request;
94     /// use rocket::http::Method;
95     ///
96     /// # Request::example(Method::Get, "/uri", |request| {
97     /// request.set_method(Method::Get);
98     /// assert_eq!(request.method(), Method::Get);
99     /// # });
100     /// ```
101     #[inline(always)]
method(&self) -> Method102     pub fn method(&self) -> Method {
103         self.method.get()
104     }
105 
106     /// Set the method of `self`.
107     ///
108     /// # Example
109     ///
110     /// ```rust
111     /// # use rocket::Request;
112     /// use rocket::http::Method;
113     ///
114     /// # Request::example(Method::Get, "/uri", |request| {
115     /// assert_eq!(request.method(), Method::Get);
116     ///
117     /// request.set_method(Method::Post);
118     /// assert_eq!(request.method(), Method::Post);
119     /// # });
120     /// ```
121     #[inline(always)]
set_method(&mut self, method: Method)122     pub fn set_method(&mut self, method: Method) {
123         self._set_method(method);
124     }
125 
126     /// Borrow the [`Origin`] URI from `self`.
127     ///
128     /// # Example
129     ///
130     /// ```rust
131     /// # use rocket::Request;
132     /// # use rocket::http::Method;
133     /// # Request::example(Method::Get, "/uri", |request| {
134     /// assert_eq!(request.uri().path(), "/uri");
135     /// # });
136     /// ```
137     #[inline(always)]
uri(&self) -> &Origin<'_>138     pub fn uri(&self) -> &Origin<'_> {
139         &self.uri
140     }
141 
142     /// Set the URI in `self` to `uri`.
143     ///
144     /// # Example
145     ///
146     /// ```rust
147     /// use rocket::http::uri::Origin;
148     ///
149     /// # use rocket::Request;
150     /// # use rocket::http::Method;
151     /// # Request::example(Method::Get, "/uri", |mut request| {
152     /// let uri = Origin::parse("/hello/Sergio?type=greeting").unwrap();
153     /// request.set_uri(uri);
154     /// assert_eq!(request.uri().path(), "/hello/Sergio");
155     /// assert_eq!(request.uri().query(), Some("type=greeting"));
156     /// # });
157     /// ```
set_uri<'u: 'r>(&mut self, uri: Origin<'u>)158     pub fn set_uri<'u: 'r>(&mut self, uri: Origin<'u>) {
159         self.uri = uri;
160         self.update_cached_uri_info();
161     }
162 
163     /// Returns the address of the remote connection that initiated this
164     /// request if the address is known. If the address is not known, `None` is
165     /// returned.
166     ///
167     /// Because it is common for proxies to forward connections for clients, the
168     /// remote address may contain information about the proxy instead of the
169     /// client. For this reason, proxies typically set the "X-Real-IP" header
170     /// with the client's true IP. To extract this IP from the request, use the
171     /// [`real_ip()`] or [`client_ip()`] methods.
172     ///
173     /// [`real_ip()`]: #method.real_ip
174     /// [`client_ip()`]: #method.client_ip
175     ///
176     /// # Example
177     ///
178     /// ```rust
179     /// # use rocket::Request;
180     /// # use rocket::http::Method;
181     /// # Request::example(Method::Get, "/uri", |request| {
182     /// assert!(request.remote().is_none());
183     /// # });
184     /// ```
185     #[inline(always)]
remote(&self) -> Option<SocketAddr>186     pub fn remote(&self) -> Option<SocketAddr> {
187         self.remote
188     }
189 
190     /// Sets the remote address of `self` to `address`.
191     ///
192     /// # Example
193     ///
194     /// Set the remote address to be 127.0.0.1:8000:
195     ///
196     /// ```rust
197     /// # use rocket::Request;
198     /// # use rocket::http::Method;
199     /// use std::net::{SocketAddr, IpAddr, Ipv4Addr};
200     ///
201     /// # Request::example(Method::Get, "/uri", |mut request| {
202     /// let (ip, port) = (IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8000);
203     /// let localhost = SocketAddr::new(ip, port);
204     /// request.set_remote(localhost);
205     ///
206     /// assert_eq!(request.remote(), Some(localhost));
207     /// # });
208     /// ```
209     #[inline(always)]
set_remote(&mut self, address: SocketAddr)210     pub fn set_remote(&mut self, address: SocketAddr) {
211         self.remote = Some(address);
212     }
213 
214     /// Returns the IP address in the "X-Real-IP" header of the request if such
215     /// a header exists and contains a valid IP address.
216     ///
217     /// # Example
218     ///
219     /// ```rust
220     /// # use rocket::Request;
221     /// # use rocket::http::{Header, Method};
222     /// # use std::net::{SocketAddr, IpAddr, Ipv4Addr};
223     ///
224     /// # Request::example(Method::Get, "/uri", |mut request| {
225     /// request.add_header(Header::new("X-Real-IP", "8.8.8.8"));
226     /// assert_eq!(request.real_ip(), Some("8.8.8.8".parse().unwrap()));
227     /// # });
228     /// ```
real_ip(&self) -> Option<IpAddr>229     pub fn real_ip(&self) -> Option<IpAddr> {
230         self.headers()
231             .get_one("X-Real-IP")
232             .and_then(|ip| {
233                 ip.parse()
234                     .map_err(|_| warn_!("'X-Real-IP' header is malformed: {}", ip))
235                     .ok()
236             })
237     }
238 
239     /// Attempts to return the client's IP address by first inspecting the
240     /// "X-Real-IP" header and then using the remote connection's IP address.
241     ///
242     /// If the "X-Real-IP" header exists and contains a valid IP address, that
243     /// address is returned. Otherwise, if the address of the remote connection
244     /// is known, that address is returned. Otherwise, `None` is returned.
245     ///
246     /// # Example
247     ///
248     /// ```rust
249     /// # use rocket::Request;
250     /// # use rocket::http::{Header, Method};
251     /// # use std::net::{SocketAddr, IpAddr, Ipv4Addr};
252     ///
253     /// # Request::example(Method::Get, "/uri", |mut request| {
254     /// // starting without an "X-Real-IP" header or remote addresss
255     /// assert!(request.client_ip().is_none());
256     ///
257     /// // add a remote address; this is done by Rocket automatically
258     /// request.set_remote("127.0.0.1:8000".parse().unwrap());
259     /// assert_eq!(request.client_ip(), Some("127.0.0.1".parse().unwrap()));
260     ///
261     /// // now with an X-Real-IP header
262     /// request.add_header(Header::new("X-Real-IP", "8.8.8.8"));
263     /// assert_eq!(request.client_ip(), Some("8.8.8.8".parse().unwrap()));
264     /// # });
265     /// ```
266     #[inline]
client_ip(&self) -> Option<IpAddr>267     pub fn client_ip(&self) -> Option<IpAddr> {
268         self.real_ip().or_else(|| self.remote().map(|r| r.ip()))
269     }
270 
271     /// Returns a wrapped borrow to the cookies in `self`.
272     ///
273     /// [`Cookies`] implements internal mutability, so this method allows you to
274     /// get _and_ add/remove cookies in `self`.
275     ///
276     /// # Example
277     ///
278     /// Add a new cookie to a request's cookies:
279     ///
280     /// ```rust
281     /// # use rocket::Request;
282     /// # use rocket::http::Method;
283     /// use rocket::http::Cookie;
284     ///
285     /// # Request::example(Method::Get, "/uri", |mut request| {
286     /// request.cookies().add(Cookie::new("key", "val"));
287     /// request.cookies().add(Cookie::new("ans", format!("life: {}", 38 + 4)));
288     /// # });
289     /// ```
cookies(&self) -> Cookies<'_>290     pub fn cookies(&self) -> Cookies<'_> {
291         // FIXME: Can we do better? This is disappointing.
292         match self.state.cookies.try_borrow_mut() {
293             Ok(jar) => Cookies::new(jar, self.state.config.secret_key()),
294             Err(_) => {
295                 error_!("Multiple `Cookies` instances are active at once.");
296                 info_!("An instance of `Cookies` must be dropped before another \
297                        can be retrieved.");
298                 warn_!("The retrieved `Cookies` instance will be empty.");
299                 Cookies::empty()
300             }
301         }
302     }
303 
304     /// Returns a [`HeaderMap`] of all of the headers in `self`.
305     ///
306     /// # Example
307     ///
308     /// ```rust
309     /// # use rocket::Request;
310     /// # use rocket::http::Method;
311     /// # Request::example(Method::Get, "/uri", |request| {
312     /// let header_map = request.headers();
313     /// assert!(header_map.is_empty());
314     /// # });
315     /// ```
316     #[inline(always)]
headers(&self) -> &HeaderMap<'r>317     pub fn headers(&self) -> &HeaderMap<'r> {
318         &self.headers
319     }
320 
321     /// Add `header` to `self`'s headers. The type of `header` can be any type
322     /// that implements the `Into<Header>` trait. This includes common types
323     /// such as [`ContentType`] and [`Accept`].
324     ///
325     /// # Example
326     ///
327     /// ```rust
328     /// # use rocket::Request;
329     /// # use rocket::http::Method;
330     /// use rocket::http::ContentType;
331     ///
332     /// # Request::example(Method::Get, "/uri", |mut request| {
333     /// assert!(request.headers().is_empty());
334     ///
335     /// request.add_header(ContentType::HTML);
336     /// assert!(request.headers().contains("Content-Type"));
337     /// assert_eq!(request.headers().len(), 1);
338     /// # });
339     /// ```
340     #[inline(always)]
add_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H)341     pub fn add_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) {
342         self.headers.add(header.into());
343     }
344 
345     /// Replaces the value of the header with name `header.name` with
346     /// `header.value`. If no such header exists, `header` is added as a header
347     /// to `self`.
348     ///
349     /// # Example
350     ///
351     /// ```rust
352     /// # use rocket::Request;
353     /// # use rocket::http::Method;
354     /// use rocket::http::ContentType;
355     ///
356     /// # Request::example(Method::Get, "/uri", |mut request| {
357     /// assert!(request.headers().is_empty());
358     ///
359     /// request.add_header(ContentType::Any);
360     /// assert_eq!(request.headers().get_one("Content-Type"), Some("*/*"));
361     ///
362     /// request.replace_header(ContentType::PNG);
363     /// assert_eq!(request.headers().get_one("Content-Type"), Some("image/png"));
364     /// # });
365     /// ```
366     #[inline(always)]
replace_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H)367     pub fn replace_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) {
368         self.headers.replace(header.into());
369     }
370 
371     /// Returns the Content-Type header of `self`. If the header is not present,
372     /// returns `None`. The Content-Type header is cached after the first call
373     /// to this function. As a result, subsequent calls will always return the
374     /// same value.
375     ///
376     /// # Example
377     ///
378     /// ```rust
379     /// # use rocket::Request;
380     /// # use rocket::http::Method;
381     /// use rocket::http::ContentType;
382     ///
383     /// # Request::example(Method::Get, "/uri", |mut request| {
384     /// request.add_header(ContentType::JSON);
385     /// assert_eq!(request.content_type(), Some(&ContentType::JSON));
386     ///
387     /// // The header is cached; it cannot be replaced after first access.
388     /// request.replace_header(ContentType::HTML);
389     /// assert_eq!(request.content_type(), Some(&ContentType::JSON));
390     /// # });
391     /// ```
392     #[inline(always)]
content_type(&self) -> Option<&ContentType>393     pub fn content_type(&self) -> Option<&ContentType> {
394         self.state.content_type.get_or_set(|| {
395             self.headers().get_one("Content-Type").and_then(|v| v.parse().ok())
396         }).as_ref()
397     }
398 
399     /// Returns the Accept header of `self`. If the header is not present,
400     /// returns `None`. The Accept header is cached after the first call to this
401     /// function. As a result, subsequent calls will always return the same
402     /// value.
403     ///
404     /// # Example
405     ///
406     /// ```rust
407     /// # use rocket::Request;
408     /// # use rocket::http::Method;
409     /// use rocket::http::Accept;
410     ///
411     /// # Request::example(Method::Get, "/uri", |mut request| {
412     /// request.add_header(Accept::JSON);
413     /// assert_eq!(request.accept(), Some(&Accept::JSON));
414     ///
415     /// // The header is cached; it cannot be replaced after first access.
416     /// request.replace_header(Accept::HTML);
417     /// assert_eq!(request.accept(), Some(&Accept::JSON));
418     /// # });
419     /// ```
420     #[inline(always)]
accept(&self) -> Option<&Accept>421     pub fn accept(&self) -> Option<&Accept> {
422         self.state.accept.get_or_set(|| {
423             self.headers().get_one("Accept").and_then(|v| v.parse().ok())
424         }).as_ref()
425     }
426 
427     /// Returns the media type "format" of the request.
428     ///
429     /// The "format" of a request is either the Content-Type, if the request
430     /// methods indicates support for a payload, or the preferred media type in
431     /// the Accept header otherwise. If the method indicates no payload and no
432     /// Accept header is specified, a media type of `Any` is returned.
433     ///
434     /// The media type returned from this method is used to match against the
435     /// `format` route attribute.
436     ///
437     /// # Example
438     ///
439     /// ```rust
440     /// # use rocket::Request;
441     /// use rocket::http::{Method, Accept, ContentType, MediaType};
442     ///
443     /// # Request::example(Method::Get, "/uri", |mut request| {
444     /// request.add_header(ContentType::JSON);
445     /// request.add_header(Accept::HTML);
446     ///
447     /// request.set_method(Method::Get);
448     /// assert_eq!(request.format(), Some(&MediaType::HTML));
449     ///
450     /// request.set_method(Method::Post);
451     /// assert_eq!(request.format(), Some(&MediaType::JSON));
452     /// # });
453     /// ```
format(&self) -> Option<&MediaType>454     pub fn format(&self) -> Option<&MediaType> {
455         static ANY: MediaType = MediaType::Any;
456         if self.method().supports_payload() {
457             self.content_type().map(|ct| ct.media_type())
458         } else {
459             // FIXME: Should we be using `accept_first` or `preferred`? Or
460             // should we be checking neither and instead pass things through
461             // where the client accepts the thing at all?
462             self.accept()
463                 .map(|accept| accept.preferred().media_type())
464                 .or(Some(&ANY))
465         }
466     }
467 
468     /// Returns the configured application receive limits.
469     ///
470     /// # Example
471     ///
472     /// ```rust
473     /// # use rocket::Request;
474     /// # use rocket::http::Method;
475     /// # Request::example(Method::Get, "/uri", |mut request| {
476     /// let json_limit = request.limits().get("json");
477     /// # });
478     /// ```
limits(&self) -> &'r Limits479     pub fn limits(&self) -> &'r Limits {
480         &self.state.config.limits
481     }
482 
483     /// Get the presently matched route, if any.
484     ///
485     /// This method returns `Some` any time a handler or its guards are being
486     /// invoked. This method returns `None` _before_ routing has commenced; this
487     /// includes during request fairing callbacks.
488     ///
489     /// # Example
490     ///
491     /// ```rust
492     /// # use rocket::Request;
493     /// # use rocket::http::Method;
494     /// # Request::example(Method::Get, "/uri", |mut request| {
495     /// let route = request.route();
496     /// # });
497     /// ```
route(&self) -> Option<&'r Route>498     pub fn route(&self) -> Option<&'r Route> {
499         self.state.route.get()
500     }
501 
502     /// Invokes the request guard implementation for `T`, returning its outcome.
503     ///
504     /// # Example
505     ///
506     /// Assuming a `User` request guard exists, invoke it:
507     ///
508     /// ```rust
509     /// # use rocket::Request;
510     /// # use rocket::http::Method;
511     /// # type User = Method;
512     /// # Request::example(Method::Get, "/uri", |request| {
513     /// let outcome = request.guard::<User>();
514     /// # });
515     /// ```
516     ///
517     /// Retrieve managed state inside of a guard implementation:
518     ///
519     /// ```rust
520     /// # use rocket::Request;
521     /// # use rocket::http::Method;
522     /// use rocket::State;
523     ///
524     /// # type Pool = usize;
525     /// # Request::example(Method::Get, "/uri", |request| {
526     /// let pool = request.guard::<State<Pool>>();
527     /// # });
528     /// ```
529     #[inline(always)]
guard<'a, T: FromRequest<'a, 'r>>(&'a self) -> Outcome<T, T::Error>530     pub fn guard<'a, T: FromRequest<'a, 'r>>(&'a self) -> Outcome<T, T::Error> {
531         T::from_request(self)
532     }
533 
534     /// Retrieves the cached value for type `T` from the request-local cached
535     /// state of `self`. If no such value has previously been cached for this
536     /// request, `f` is called to produce the value which is subsequently
537     /// returned.
538     ///
539     /// # Example
540     ///
541     /// ```rust
542     /// # use rocket::http::Method;
543     /// # use rocket::Request;
544     /// # type User = ();
545     /// fn current_user(request: &Request) -> User {
546     ///     // Validate request for a given user, load from database, etc.
547     /// }
548     ///
549     /// # Request::example(Method::Get, "/uri", |request| {
550     /// let user = request.local_cache(|| current_user(request));
551     /// # });
552     /// ```
local_cache<T, F>(&self, f: F) -> &T where F: FnOnce() -> T, T: Send + Sync + 'static553     pub fn local_cache<T, F>(&self, f: F) -> &T
554         where F: FnOnce() -> T,
555               T: Send + Sync + 'static
556     {
557         self.state.cache.try_get()
558             .unwrap_or_else(|| {
559                 self.state.cache.set(f());
560                 self.state.cache.get()
561             })
562     }
563 
564     /// Retrieves and parses into `T` the 0-indexed `n`th segment from the
565     /// request. Returns `None` if `n` is greater than the number of segments.
566     /// Returns `Some(Err(T::Error))` if the parameter type `T` failed to be
567     /// parsed from the `n`th dynamic parameter.
568     ///
569     /// This method exists only to be used by manual routing. To retrieve
570     /// parameters from a request, use Rocket's code generation facilities.
571     ///
572     /// # Example
573     ///
574     /// ```rust
575     /// # use rocket::{Request, http::Method};
576     /// use rocket::http::{RawStr, uri::Origin};
577     ///
578     /// # Request::example(Method::Get, "/", |req| {
579     /// fn string<'s>(req: &'s mut Request, uri: &'static str, n: usize) -> &'s RawStr {
580     ///     req.set_uri(Origin::parse(uri).unwrap());
581     ///
582     ///     req.get_param(n)
583     ///         .and_then(|r| r.ok())
584     ///         .unwrap_or("unnamed".into())
585     /// }
586     ///
587     /// assert_eq!(string(req, "/", 0).as_str(), "unnamed");
588     /// assert_eq!(string(req, "/a/b/this_one", 0).as_str(), "a");
589     /// assert_eq!(string(req, "/a/b/this_one", 1).as_str(), "b");
590     /// assert_eq!(string(req, "/a/b/this_one", 2).as_str(), "this_one");
591     /// assert_eq!(string(req, "/a/b/this_one", 3).as_str(), "unnamed");
592     /// assert_eq!(string(req, "/a/b/c/d/e/f/g/h", 7).as_str(), "h");
593     /// # });
594     /// ```
595     #[inline]
get_param<'a, T>(&'a self, n: usize) -> Option<Result<T, T::Error>> where T: FromParam<'a>596     pub fn get_param<'a, T>(&'a self, n: usize) -> Option<Result<T, T::Error>>
597         where T: FromParam<'a>
598     {
599         Some(T::from_param(self.raw_segment_str(n)?))
600     }
601 
602     /// Retrieves and parses into `T` all of the path segments in the request
603     /// URI beginning and including the 0-indexed `n`th non-empty segment. `T`
604     /// must implement [`FromSegments`], which is used to parse the segments.
605     ///
606     /// This method exists only to be used by manual routing. To retrieve
607     /// segments from a request, use Rocket's code generation facilities.
608     ///
609     /// # Error
610     ///
611     /// If there are fewer than `n` non-empty segments, returns `None`. If
612     /// parsing the segments failed, returns `Some(Err(T:Error))`.
613     ///
614     /// # Example
615     ///
616     /// ```rust
617     /// # use rocket::{Request, http::Method};
618     /// use std::path::PathBuf;
619     ///
620     /// use rocket::http::uri::Origin;
621     ///
622     /// # Request::example(Method::Get, "/", |req| {
623     /// fn path<'s>(req: &'s mut Request, uri: &'static str, n: usize) -> PathBuf {
624     ///     req.set_uri(Origin::parse(uri).unwrap());
625     ///
626     ///     req.get_segments(n)
627     ///         .and_then(|r| r.ok())
628     ///         .unwrap_or_else(|| "whoops".into())
629     /// }
630     ///
631     /// assert_eq!(path(req, "/", 0), PathBuf::from("whoops"));
632     /// assert_eq!(path(req, "/a/", 0), PathBuf::from("a"));
633     /// assert_eq!(path(req, "/a/b/c", 0), PathBuf::from("a/b/c"));
634     /// assert_eq!(path(req, "/a/b/c", 1), PathBuf::from("b/c"));
635     /// assert_eq!(path(req, "/a/b/c", 2), PathBuf::from("c"));
636     /// assert_eq!(path(req, "/a/b/c", 6), PathBuf::from("whoops"));
637     /// # });
638     /// ```
639     #[inline]
get_segments<'a, T>(&'a self, n: usize) -> Option<Result<T, T::Error>> where T: FromSegments<'a>640     pub fn get_segments<'a, T>(&'a self, n: usize) -> Option<Result<T, T::Error>>
641         where T: FromSegments<'a>
642     {
643         Some(T::from_segments(self.raw_segments(n)?))
644     }
645 
646     /// Retrieves and parses into `T` the query value with key `key`. `T` must
647     /// implement [`FromFormValue`], which is used to parse the query's value.
648     /// Key matching is performed case-sensitively. If there are multiple pairs
649     /// with key `key`, the _last_ one is returned.
650     ///
651     /// This method exists only to be used by manual routing. To retrieve
652     /// query values from a request, use Rocket's code generation facilities.
653     ///
654     /// # Error
655     ///
656     /// If a query segment with key `key` isn't present, returns `None`. If
657     /// parsing the value fails, returns `Some(Err(T:Error))`.
658     ///
659     /// # Example
660     ///
661     /// ```rust
662     /// # use rocket::{Request, http::Method};
663     /// use std::path::PathBuf;
664     /// use rocket::http::{RawStr, uri::Origin};
665     ///
666     /// # Request::example(Method::Get, "/", |req| {
667     /// fn value<'s>(req: &'s mut Request, uri: &'static str, key: &str) -> &'s RawStr {
668     ///     req.set_uri(Origin::parse(uri).unwrap());
669     ///
670     ///     req.get_query_value(key)
671     ///         .and_then(|r| r.ok())
672     ///         .unwrap_or("n/a".into())
673     /// }
674     ///
675     /// assert_eq!(value(req, "/?a=apple&z=zebra", "a").as_str(), "apple");
676     /// assert_eq!(value(req, "/?a=apple&z=zebra", "z").as_str(), "zebra");
677     /// assert_eq!(value(req, "/?a=apple&z=zebra", "A").as_str(), "n/a");
678     /// assert_eq!(value(req, "/?a=apple&z=zebra&a=argon", "a").as_str(), "argon");
679     /// assert_eq!(value(req, "/?a=1&a=2&a=3&b=4", "a").as_str(), "3");
680     /// assert_eq!(value(req, "/?a=apple&z=zebra", "apple").as_str(), "n/a");
681     /// # });
682     /// ```
683     #[inline]
get_query_value<'a, T>(&'a self, key: &str) -> Option<Result<T, T::Error>> where T: FromFormValue<'a>684     pub fn get_query_value<'a, T>(&'a self, key: &str) -> Option<Result<T, T::Error>>
685         where T: FromFormValue<'a>
686     {
687         self.raw_query_items()?
688             .rev()
689             .find(|item| item.key.as_str() == key)
690             .map(|item| T::from_form_value(item.value))
691     }
692 }
693 
694 // All of these methods only exist for internal, including codegen, purposes.
695 // They _are not_ part of the stable API.
696 #[doc(hidden)]
697 impl<'r> Request<'r> {
698     // Only used by doc-tests! Needs to be `pub` because doc-test are external.
example<F: Fn(&mut Request<'_>)>(method: Method, uri: &str, f: F)699     pub fn example<F: Fn(&mut Request<'_>)>(method: Method, uri: &str, f: F) {
700         let rocket = Rocket::custom(Config::development());
701         let uri = Origin::parse(uri).expect("invalid URI in example");
702         let mut request = Request::new(&rocket, method, uri);
703         f(&mut request);
704     }
705 
706     // Updates the cached `path_segments` and `query_items` in `self.state`.
707     // MUST be called whenever a new URI is set or updated.
708     #[inline]
update_cached_uri_info(&mut self)709     fn update_cached_uri_info(&mut self) {
710         let path_segments = Segments(self.uri.path())
711             .map(|s| indices(s, self.uri.path()))
712             .collect();
713 
714         let query_items = self.uri.query()
715             .map(|query_str| FormItems::from(query_str)
716                  .map(|item| IndexedFormItem::from(query_str, item))
717                  .collect()
718             );
719 
720         self.state.path_segments = path_segments;
721         self.state.query_items = query_items;
722     }
723 
724     /// Get the `n`th path segment, 0-indexed, after the mount point for the
725     /// currently matched route, as a string, if it exists. Used by codegen.
726     #[inline]
raw_segment_str(&self, n: usize) -> Option<&RawStr>727     pub fn raw_segment_str(&self, n: usize) -> Option<&RawStr> {
728         self.routed_path_segment(n)
729             .map(|(i, j)| self.uri.path()[i..j].into())
730     }
731 
732     /// Get the segments beginning at the `n`th, 0-indexed, after the mount
733     /// point for the currently matched route, if they exist. Used by codegen.
734     #[inline]
raw_segments(&self, n: usize) -> Option<Segments<'_>>735     pub fn raw_segments(&self, n: usize) -> Option<Segments<'_>> {
736         self.routed_path_segment(n)
737             .map(|(i, _)| Segments(&self.uri.path()[i..]) )
738     }
739 
740     // Returns an iterator over the raw segments of the path URI. Does not take
741     // into account the current route. This is used during routing.
742     #[inline]
raw_path_segments(&self) -> impl Iterator<Item = &RawStr>743     pub(crate) fn raw_path_segments(&self) -> impl Iterator<Item = &RawStr> {
744         let path = self.uri.path();
745         self.state.path_segments.iter().cloned()
746             .map(move |(i, j)| path[i..j].into())
747     }
748 
749     #[inline]
routed_path_segment(&self, n: usize) -> Option<(usize, usize)>750     fn routed_path_segment(&self, n: usize) -> Option<(usize, usize)> {
751         let mount_segments = self.route()
752             .map(|r| r.base.segment_count())
753             .unwrap_or(0);
754 
755         self.state.path_segments.get(mount_segments + n).map(|(i, j)| (*i, *j))
756     }
757 
758     // Retrieves the pre-parsed query items. Used by matching and codegen.
759     #[inline]
raw_query_items( &self ) -> Option<impl Iterator<Item = FormItem<'_>> + DoubleEndedIterator + Clone>760     pub fn raw_query_items(
761         &self
762     ) -> Option<impl Iterator<Item = FormItem<'_>> + DoubleEndedIterator + Clone> {
763         let query = self.uri.query()?;
764         self.state.query_items.as_ref().map(move |items| {
765             items.iter().map(move |item| item.convert(query))
766         })
767     }
768 
769     /// Set `self`'s parameters given that the route used to reach this request
770     /// was `route`. Use during routing when attempting a given route.
771     #[inline(always)]
set_route(&self, route: &'r Route)772     pub(crate) fn set_route(&self, route: &'r Route) {
773         self.state.route.set(Some(route));
774     }
775 
776     /// Set the method of `self`, even when `self` is a shared reference. Used
777     /// during routing to override methods for re-routing.
778     #[inline(always)]
_set_method(&self, method: Method)779     pub(crate) fn _set_method(&self, method: Method) {
780         self.method.set(method);
781     }
782 
783     /// Convert from Hyper types into a Rocket Request.
from_hyp( rocket: &'r Rocket, h_method: hyper::Method, h_headers: hyper::header::Headers, h_uri: hyper::RequestUri, h_addr: SocketAddr, ) -> Result<Request<'r>, String>784     pub(crate) fn from_hyp(
785         rocket: &'r Rocket,
786         h_method: hyper::Method,
787         h_headers: hyper::header::Headers,
788         h_uri: hyper::RequestUri,
789         h_addr: SocketAddr,
790     ) -> Result<Request<'r>, String> {
791         // Get a copy of the URI for later use.
792         let uri = match h_uri {
793             hyper::RequestUri::AbsolutePath(s) => s,
794             _ => return Err(format!("Bad URI: {}", h_uri)),
795         };
796 
797         // Ensure that the method is known. TODO: Allow made-up methods?
798         let method = match Method::from_hyp(&h_method) {
799             Some(method) => method,
800             None => return Err(format!("Invalid method: {}", h_method))
801         };
802 
803         // We need to re-parse the URI since we don't trust Hyper... :(
804         let uri = Origin::parse_owned(uri).map_err(|e| e.to_string())?;
805 
806         // Construct the request object.
807         let mut request = Request::new(rocket, method, uri);
808         request.set_remote(h_addr);
809 
810         // Set the request cookies, if they exist.
811         if let Some(cookie_headers) = h_headers.get_raw("Cookie") {
812             let mut cookie_jar = CookieJar::new();
813             for header in cookie_headers {
814                 let raw_str = match std::str::from_utf8(header) {
815                     Ok(string) => string,
816                     Err(_) => continue
817                 };
818 
819                 for cookie_str in raw_str.split(';').map(|s| s.trim()) {
820                     if let Some(cookie) = Cookies::parse_cookie(cookie_str) {
821                         cookie_jar.add_original(cookie);
822                     }
823                 }
824             }
825 
826             request.state.cookies = RefCell::new(cookie_jar);
827         }
828 
829         // Set the rest of the headers.
830         for hyp in h_headers.iter() {
831             if let Some(header_values) = h_headers.get_raw(hyp.name()) {
832                 for value in header_values {
833                     // This is not totally correct since values needn't be UTF8.
834                     let value_str = String::from_utf8_lossy(value).into_owned();
835                     let header = Header::new(hyp.name().to_string(), value_str);
836                     request.add_header(header);
837                 }
838             }
839         }
840 
841         Ok(request)
842     }
843 }
844 
845 impl fmt::Debug for Request<'_> {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result846     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
847         fmt.debug_struct("Request")
848             .field("method", &self.method)
849             .field("uri", &self.uri)
850             .field("headers", &self.headers())
851             .field("remote", &self.remote())
852             .finish()
853     }
854 }
855 
856 impl fmt::Display for Request<'_> {
857     /// Pretty prints a Request. This is primarily used by Rocket's logging
858     /// infrastructure.
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result859     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
860         write!(f, "{} {}", Paint::green(self.method()), Paint::blue(&self.uri))?;
861 
862         // Print the requests media type when the route specifies a format.
863         if let Some(media_type) = self.format() {
864             if !media_type.is_any() {
865                 write!(f, " {}", Paint::yellow(media_type))?;
866             }
867         }
868 
869         Ok(())
870     }
871 }
872 
873 impl IndexedFormItem {
874     #[inline(always)]
from(s: &str, i: FormItem<'_>) -> Self875     fn from(s: &str, i: FormItem<'_>) -> Self {
876         let (r, k, v) = (indices(i.raw, s), indices(i.key, s), indices(i.value, s));
877         IndexedFormItem { raw: r, key: k, value: v }
878     }
879 
880     #[inline(always)]
convert<'s>(&self, source: &'s str) -> FormItem<'s>881     fn convert<'s>(&self, source: &'s str) -> FormItem<'s> {
882         FormItem {
883             raw: source[self.raw.0..self.raw.1].into(),
884             key: source[self.key.0..self.key.1].into(),
885             value: source[self.value.0..self.value.1].into(),
886         }
887     }
888 }
889 
indices(needle: &str, haystack: &str) -> (usize, usize)890 fn indices(needle: &str, haystack: &str) -> (usize, usize) {
891     Indexed::checked_from(needle, haystack)
892         .expect("segments inside of path/query")
893         .indices()
894 }
895