use std::rc::Rc; use std::cell::{Cell, RefCell}; use std::net::{IpAddr, SocketAddr}; use std::fmt; use std::str; use yansi::Paint; use state::{Container, Storage}; use crate::request::{FromParam, FromSegments, FromRequest, Outcome}; use crate::request::{FromFormValue, FormItems, FormItem}; use crate::rocket::Rocket; use crate::router::Route; use crate::config::{Config, Limits}; use crate::http::{hyper, uri::{Origin, Segments}}; use crate::http::{Method, Header, HeaderMap, Cookies}; use crate::http::{RawStr, ContentType, Accept, MediaType}; use crate::http::private::{Indexed, SmallVec, CookieJar}; type Indices = (usize, usize); /// The type of an incoming web request. /// /// This should be used sparingly in Rocket applications. In particular, it /// should likely only be used when writing [`FromRequest`] implementations. It /// contains all of the information for a given web request except for the body /// data. This includes the HTTP method, URI, cookies, headers, and more. #[derive(Clone)] pub struct Request<'r> { method: Cell, uri: Origin<'r>, headers: HeaderMap<'r>, remote: Option, pub(crate) state: RequestState<'r>, } #[derive(Clone)] pub(crate) struct RequestState<'r> { pub config: &'r Config, pub managed: &'r Container, pub path_segments: SmallVec<[Indices; 12]>, pub query_items: Option>, pub route: Cell>, pub cookies: RefCell, pub accept: Storage>, pub content_type: Storage>, pub cache: Rc, } #[derive(Clone)] pub(crate) struct IndexedFormItem { raw: Indices, key: Indices, value: Indices } impl<'r> Request<'r> { /// Create a new `Request` with the given `method` and `uri`. #[inline(always)] pub(crate) fn new<'s: 'r>( rocket: &'r Rocket, method: Method, uri: Origin<'s> ) -> Request<'r> { let mut request = Request { method: Cell::new(method), uri: uri, headers: HeaderMap::new(), remote: None, state: RequestState { path_segments: SmallVec::new(), query_items: None, config: &rocket.config, managed: &rocket.state, route: Cell::new(None), cookies: RefCell::new(CookieJar::new()), accept: Storage::new(), content_type: Storage::new(), cache: Rc::new(Container::new()), } }; request.update_cached_uri_info(); request } /// Retrieve the method from `self`. /// /// # Example /// /// ```rust /// # use rocket::Request; /// use rocket::http::Method; /// /// # Request::example(Method::Get, "/uri", |request| { /// request.set_method(Method::Get); /// assert_eq!(request.method(), Method::Get); /// # }); /// ``` #[inline(always)] pub fn method(&self) -> Method { self.method.get() } /// Set the method of `self`. /// /// # Example /// /// ```rust /// # use rocket::Request; /// use rocket::http::Method; /// /// # Request::example(Method::Get, "/uri", |request| { /// assert_eq!(request.method(), Method::Get); /// /// request.set_method(Method::Post); /// assert_eq!(request.method(), Method::Post); /// # }); /// ``` #[inline(always)] pub fn set_method(&mut self, method: Method) { self._set_method(method); } /// Borrow the [`Origin`] URI from `self`. /// /// # Example /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// # Request::example(Method::Get, "/uri", |request| { /// assert_eq!(request.uri().path(), "/uri"); /// # }); /// ``` #[inline(always)] pub fn uri(&self) -> &Origin<'_> { &self.uri } /// Set the URI in `self` to `uri`. /// /// # Example /// /// ```rust /// use rocket::http::uri::Origin; /// /// # use rocket::Request; /// # use rocket::http::Method; /// # Request::example(Method::Get, "/uri", |mut request| { /// let uri = Origin::parse("/hello/Sergio?type=greeting").unwrap(); /// request.set_uri(uri); /// assert_eq!(request.uri().path(), "/hello/Sergio"); /// assert_eq!(request.uri().query(), Some("type=greeting")); /// # }); /// ``` pub fn set_uri<'u: 'r>(&mut self, uri: Origin<'u>) { self.uri = uri; self.update_cached_uri_info(); } /// Returns the address of the remote connection that initiated this /// request if the address is known. If the address is not known, `None` is /// returned. /// /// Because it is common for proxies to forward connections for clients, the /// remote address may contain information about the proxy instead of the /// client. For this reason, proxies typically set the "X-Real-IP" header /// with the client's true IP. To extract this IP from the request, use the /// [`real_ip()`] or [`client_ip()`] methods. /// /// [`real_ip()`]: #method.real_ip /// [`client_ip()`]: #method.client_ip /// /// # Example /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// # Request::example(Method::Get, "/uri", |request| { /// assert!(request.remote().is_none()); /// # }); /// ``` #[inline(always)] pub fn remote(&self) -> Option { self.remote } /// Sets the remote address of `self` to `address`. /// /// # Example /// /// Set the remote address to be 127.0.0.1:8000: /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// use std::net::{SocketAddr, IpAddr, Ipv4Addr}; /// /// # Request::example(Method::Get, "/uri", |mut request| { /// let (ip, port) = (IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8000); /// let localhost = SocketAddr::new(ip, port); /// request.set_remote(localhost); /// /// assert_eq!(request.remote(), Some(localhost)); /// # }); /// ``` #[inline(always)] pub fn set_remote(&mut self, address: SocketAddr) { self.remote = Some(address); } /// Returns the IP address in the "X-Real-IP" header of the request if such /// a header exists and contains a valid IP address. /// /// # Example /// /// ```rust /// # use rocket::Request; /// # use rocket::http::{Header, Method}; /// # use std::net::{SocketAddr, IpAddr, Ipv4Addr}; /// /// # Request::example(Method::Get, "/uri", |mut request| { /// request.add_header(Header::new("X-Real-IP", "8.8.8.8")); /// assert_eq!(request.real_ip(), Some("8.8.8.8".parse().unwrap())); /// # }); /// ``` pub fn real_ip(&self) -> Option { self.headers() .get_one("X-Real-IP") .and_then(|ip| { ip.parse() .map_err(|_| warn_!("'X-Real-IP' header is malformed: {}", ip)) .ok() }) } /// Attempts to return the client's IP address by first inspecting the /// "X-Real-IP" header and then using the remote connection's IP address. /// /// If the "X-Real-IP" header exists and contains a valid IP address, that /// address is returned. Otherwise, if the address of the remote connection /// is known, that address is returned. Otherwise, `None` is returned. /// /// # Example /// /// ```rust /// # use rocket::Request; /// # use rocket::http::{Header, Method}; /// # use std::net::{SocketAddr, IpAddr, Ipv4Addr}; /// /// # Request::example(Method::Get, "/uri", |mut request| { /// // starting without an "X-Real-IP" header or remote addresss /// assert!(request.client_ip().is_none()); /// /// // add a remote address; this is done by Rocket automatically /// request.set_remote("127.0.0.1:8000".parse().unwrap()); /// assert_eq!(request.client_ip(), Some("127.0.0.1".parse().unwrap())); /// /// // now with an X-Real-IP header /// request.add_header(Header::new("X-Real-IP", "8.8.8.8")); /// assert_eq!(request.client_ip(), Some("8.8.8.8".parse().unwrap())); /// # }); /// ``` #[inline] pub fn client_ip(&self) -> Option { self.real_ip().or_else(|| self.remote().map(|r| r.ip())) } /// Returns a wrapped borrow to the cookies in `self`. /// /// [`Cookies`] implements internal mutability, so this method allows you to /// get _and_ add/remove cookies in `self`. /// /// # Example /// /// Add a new cookie to a request's cookies: /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// use rocket::http::Cookie; /// /// # Request::example(Method::Get, "/uri", |mut request| { /// request.cookies().add(Cookie::new("key", "val")); /// request.cookies().add(Cookie::new("ans", format!("life: {}", 38 + 4))); /// # }); /// ``` pub fn cookies(&self) -> Cookies<'_> { // FIXME: Can we do better? This is disappointing. match self.state.cookies.try_borrow_mut() { Ok(jar) => Cookies::new(jar, self.state.config.secret_key()), Err(_) => { error_!("Multiple `Cookies` instances are active at once."); info_!("An instance of `Cookies` must be dropped before another \ can be retrieved."); warn_!("The retrieved `Cookies` instance will be empty."); Cookies::empty() } } } /// Returns a [`HeaderMap`] of all of the headers in `self`. /// /// # Example /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// # Request::example(Method::Get, "/uri", |request| { /// let header_map = request.headers(); /// assert!(header_map.is_empty()); /// # }); /// ``` #[inline(always)] pub fn headers(&self) -> &HeaderMap<'r> { &self.headers } /// Add `header` to `self`'s headers. The type of `header` can be any type /// that implements the `Into
` trait. This includes common types /// such as [`ContentType`] and [`Accept`]. /// /// # Example /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// use rocket::http::ContentType; /// /// # Request::example(Method::Get, "/uri", |mut request| { /// assert!(request.headers().is_empty()); /// /// request.add_header(ContentType::HTML); /// assert!(request.headers().contains("Content-Type")); /// assert_eq!(request.headers().len(), 1); /// # }); /// ``` #[inline(always)] pub fn add_header<'h: 'r, H: Into>>(&mut self, header: H) { self.headers.add(header.into()); } /// Replaces the value of the header with name `header.name` with /// `header.value`. If no such header exists, `header` is added as a header /// to `self`. /// /// # Example /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// use rocket::http::ContentType; /// /// # Request::example(Method::Get, "/uri", |mut request| { /// assert!(request.headers().is_empty()); /// /// request.add_header(ContentType::Any); /// assert_eq!(request.headers().get_one("Content-Type"), Some("*/*")); /// /// request.replace_header(ContentType::PNG); /// assert_eq!(request.headers().get_one("Content-Type"), Some("image/png")); /// # }); /// ``` #[inline(always)] pub fn replace_header<'h: 'r, H: Into>>(&mut self, header: H) { self.headers.replace(header.into()); } /// Returns the Content-Type header of `self`. If the header is not present, /// returns `None`. The Content-Type header is cached after the first call /// to this function. As a result, subsequent calls will always return the /// same value. /// /// # Example /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// use rocket::http::ContentType; /// /// # Request::example(Method::Get, "/uri", |mut request| { /// request.add_header(ContentType::JSON); /// assert_eq!(request.content_type(), Some(&ContentType::JSON)); /// /// // The header is cached; it cannot be replaced after first access. /// request.replace_header(ContentType::HTML); /// assert_eq!(request.content_type(), Some(&ContentType::JSON)); /// # }); /// ``` #[inline(always)] pub fn content_type(&self) -> Option<&ContentType> { self.state.content_type.get_or_set(|| { self.headers().get_one("Content-Type").and_then(|v| v.parse().ok()) }).as_ref() } /// Returns the Accept header of `self`. If the header is not present, /// returns `None`. The Accept header is cached after the first call to this /// function. As a result, subsequent calls will always return the same /// value. /// /// # Example /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// use rocket::http::Accept; /// /// # Request::example(Method::Get, "/uri", |mut request| { /// request.add_header(Accept::JSON); /// assert_eq!(request.accept(), Some(&Accept::JSON)); /// /// // The header is cached; it cannot be replaced after first access. /// request.replace_header(Accept::HTML); /// assert_eq!(request.accept(), Some(&Accept::JSON)); /// # }); /// ``` #[inline(always)] pub fn accept(&self) -> Option<&Accept> { self.state.accept.get_or_set(|| { self.headers().get_one("Accept").and_then(|v| v.parse().ok()) }).as_ref() } /// Returns the media type "format" of the request. /// /// The "format" of a request is either the Content-Type, if the request /// methods indicates support for a payload, or the preferred media type in /// the Accept header otherwise. If the method indicates no payload and no /// Accept header is specified, a media type of `Any` is returned. /// /// The media type returned from this method is used to match against the /// `format` route attribute. /// /// # Example /// /// ```rust /// # use rocket::Request; /// use rocket::http::{Method, Accept, ContentType, MediaType}; /// /// # Request::example(Method::Get, "/uri", |mut request| { /// request.add_header(ContentType::JSON); /// request.add_header(Accept::HTML); /// /// request.set_method(Method::Get); /// assert_eq!(request.format(), Some(&MediaType::HTML)); /// /// request.set_method(Method::Post); /// assert_eq!(request.format(), Some(&MediaType::JSON)); /// # }); /// ``` pub fn format(&self) -> Option<&MediaType> { static ANY: MediaType = MediaType::Any; if self.method().supports_payload() { self.content_type().map(|ct| ct.media_type()) } else { // FIXME: Should we be using `accept_first` or `preferred`? Or // should we be checking neither and instead pass things through // where the client accepts the thing at all? self.accept() .map(|accept| accept.preferred().media_type()) .or(Some(&ANY)) } } /// Returns the configured application receive limits. /// /// # Example /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// # Request::example(Method::Get, "/uri", |mut request| { /// let json_limit = request.limits().get("json"); /// # }); /// ``` pub fn limits(&self) -> &'r Limits { &self.state.config.limits } /// Get the presently matched route, if any. /// /// This method returns `Some` any time a handler or its guards are being /// invoked. This method returns `None` _before_ routing has commenced; this /// includes during request fairing callbacks. /// /// # Example /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// # Request::example(Method::Get, "/uri", |mut request| { /// let route = request.route(); /// # }); /// ``` pub fn route(&self) -> Option<&'r Route> { self.state.route.get() } /// Invokes the request guard implementation for `T`, returning its outcome. /// /// # Example /// /// Assuming a `User` request guard exists, invoke it: /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// # type User = Method; /// # Request::example(Method::Get, "/uri", |request| { /// let outcome = request.guard::(); /// # }); /// ``` /// /// Retrieve managed state inside of a guard implementation: /// /// ```rust /// # use rocket::Request; /// # use rocket::http::Method; /// use rocket::State; /// /// # type Pool = usize; /// # Request::example(Method::Get, "/uri", |request| { /// let pool = request.guard::>(); /// # }); /// ``` #[inline(always)] pub fn guard<'a, T: FromRequest<'a, 'r>>(&'a self) -> Outcome { T::from_request(self) } /// Retrieves the cached value for type `T` from the request-local cached /// state of `self`. If no such value has previously been cached for this /// request, `f` is called to produce the value which is subsequently /// returned. /// /// # Example /// /// ```rust /// # use rocket::http::Method; /// # use rocket::Request; /// # type User = (); /// fn current_user(request: &Request) -> User { /// // Validate request for a given user, load from database, etc. /// } /// /// # Request::example(Method::Get, "/uri", |request| { /// let user = request.local_cache(|| current_user(request)); /// # }); /// ``` pub fn local_cache(&self, f: F) -> &T where F: FnOnce() -> T, T: Send + Sync + 'static { self.state.cache.try_get() .unwrap_or_else(|| { self.state.cache.set(f()); self.state.cache.get() }) } /// Retrieves and parses into `T` the 0-indexed `n`th segment from the /// request. Returns `None` if `n` is greater than the number of segments. /// Returns `Some(Err(T::Error))` if the parameter type `T` failed to be /// parsed from the `n`th dynamic parameter. /// /// This method exists only to be used by manual routing. To retrieve /// parameters from a request, use Rocket's code generation facilities. /// /// # Example /// /// ```rust /// # use rocket::{Request, http::Method}; /// use rocket::http::{RawStr, uri::Origin}; /// /// # Request::example(Method::Get, "/", |req| { /// fn string<'s>(req: &'s mut Request, uri: &'static str, n: usize) -> &'s RawStr { /// req.set_uri(Origin::parse(uri).unwrap()); /// /// req.get_param(n) /// .and_then(|r| r.ok()) /// .unwrap_or("unnamed".into()) /// } /// /// assert_eq!(string(req, "/", 0).as_str(), "unnamed"); /// assert_eq!(string(req, "/a/b/this_one", 0).as_str(), "a"); /// assert_eq!(string(req, "/a/b/this_one", 1).as_str(), "b"); /// assert_eq!(string(req, "/a/b/this_one", 2).as_str(), "this_one"); /// assert_eq!(string(req, "/a/b/this_one", 3).as_str(), "unnamed"); /// assert_eq!(string(req, "/a/b/c/d/e/f/g/h", 7).as_str(), "h"); /// # }); /// ``` #[inline] pub fn get_param<'a, T>(&'a self, n: usize) -> Option> where T: FromParam<'a> { Some(T::from_param(self.raw_segment_str(n)?)) } /// Retrieves and parses into `T` all of the path segments in the request /// URI beginning and including the 0-indexed `n`th non-empty segment. `T` /// must implement [`FromSegments`], which is used to parse the segments. /// /// This method exists only to be used by manual routing. To retrieve /// segments from a request, use Rocket's code generation facilities. /// /// # Error /// /// If there are fewer than `n` non-empty segments, returns `None`. If /// parsing the segments failed, returns `Some(Err(T:Error))`. /// /// # Example /// /// ```rust /// # use rocket::{Request, http::Method}; /// use std::path::PathBuf; /// /// use rocket::http::uri::Origin; /// /// # Request::example(Method::Get, "/", |req| { /// fn path<'s>(req: &'s mut Request, uri: &'static str, n: usize) -> PathBuf { /// req.set_uri(Origin::parse(uri).unwrap()); /// /// req.get_segments(n) /// .and_then(|r| r.ok()) /// .unwrap_or_else(|| "whoops".into()) /// } /// /// assert_eq!(path(req, "/", 0), PathBuf::from("whoops")); /// assert_eq!(path(req, "/a/", 0), PathBuf::from("a")); /// assert_eq!(path(req, "/a/b/c", 0), PathBuf::from("a/b/c")); /// assert_eq!(path(req, "/a/b/c", 1), PathBuf::from("b/c")); /// assert_eq!(path(req, "/a/b/c", 2), PathBuf::from("c")); /// assert_eq!(path(req, "/a/b/c", 6), PathBuf::from("whoops")); /// # }); /// ``` #[inline] pub fn get_segments<'a, T>(&'a self, n: usize) -> Option> where T: FromSegments<'a> { Some(T::from_segments(self.raw_segments(n)?)) } /// Retrieves and parses into `T` the query value with key `key`. `T` must /// implement [`FromFormValue`], which is used to parse the query's value. /// Key matching is performed case-sensitively. If there are multiple pairs /// with key `key`, the _last_ one is returned. /// /// This method exists only to be used by manual routing. To retrieve /// query values from a request, use Rocket's code generation facilities. /// /// # Error /// /// If a query segment with key `key` isn't present, returns `None`. If /// parsing the value fails, returns `Some(Err(T:Error))`. /// /// # Example /// /// ```rust /// # use rocket::{Request, http::Method}; /// use std::path::PathBuf; /// use rocket::http::{RawStr, uri::Origin}; /// /// # Request::example(Method::Get, "/", |req| { /// fn value<'s>(req: &'s mut Request, uri: &'static str, key: &str) -> &'s RawStr { /// req.set_uri(Origin::parse(uri).unwrap()); /// /// req.get_query_value(key) /// .and_then(|r| r.ok()) /// .unwrap_or("n/a".into()) /// } /// /// assert_eq!(value(req, "/?a=apple&z=zebra", "a").as_str(), "apple"); /// assert_eq!(value(req, "/?a=apple&z=zebra", "z").as_str(), "zebra"); /// assert_eq!(value(req, "/?a=apple&z=zebra", "A").as_str(), "n/a"); /// assert_eq!(value(req, "/?a=apple&z=zebra&a=argon", "a").as_str(), "argon"); /// assert_eq!(value(req, "/?a=1&a=2&a=3&b=4", "a").as_str(), "3"); /// assert_eq!(value(req, "/?a=apple&z=zebra", "apple").as_str(), "n/a"); /// # }); /// ``` #[inline] pub fn get_query_value<'a, T>(&'a self, key: &str) -> Option> where T: FromFormValue<'a> { self.raw_query_items()? .rev() .find(|item| item.key.as_str() == key) .map(|item| T::from_form_value(item.value)) } } // All of these methods only exist for internal, including codegen, purposes. // They _are not_ part of the stable API. #[doc(hidden)] impl<'r> Request<'r> { // Only used by doc-tests! Needs to be `pub` because doc-test are external. pub fn example)>(method: Method, uri: &str, f: F) { let rocket = Rocket::custom(Config::development()); let uri = Origin::parse(uri).expect("invalid URI in example"); let mut request = Request::new(&rocket, method, uri); f(&mut request); } // Updates the cached `path_segments` and `query_items` in `self.state`. // MUST be called whenever a new URI is set or updated. #[inline] fn update_cached_uri_info(&mut self) { let path_segments = Segments(self.uri.path()) .map(|s| indices(s, self.uri.path())) .collect(); let query_items = self.uri.query() .map(|query_str| FormItems::from(query_str) .map(|item| IndexedFormItem::from(query_str, item)) .collect() ); self.state.path_segments = path_segments; self.state.query_items = query_items; } /// Get the `n`th path segment, 0-indexed, after the mount point for the /// currently matched route, as a string, if it exists. Used by codegen. #[inline] pub fn raw_segment_str(&self, n: usize) -> Option<&RawStr> { self.routed_path_segment(n) .map(|(i, j)| self.uri.path()[i..j].into()) } /// Get the segments beginning at the `n`th, 0-indexed, after the mount /// point for the currently matched route, if they exist. Used by codegen. #[inline] pub fn raw_segments(&self, n: usize) -> Option> { self.routed_path_segment(n) .map(|(i, _)| Segments(&self.uri.path()[i..]) ) } // Returns an iterator over the raw segments of the path URI. Does not take // into account the current route. This is used during routing. #[inline] pub(crate) fn raw_path_segments(&self) -> impl Iterator { let path = self.uri.path(); self.state.path_segments.iter().cloned() .map(move |(i, j)| path[i..j].into()) } #[inline] fn routed_path_segment(&self, n: usize) -> Option<(usize, usize)> { let mount_segments = self.route() .map(|r| r.base.segment_count()) .unwrap_or(0); self.state.path_segments.get(mount_segments + n).map(|(i, j)| (*i, *j)) } // Retrieves the pre-parsed query items. Used by matching and codegen. #[inline] pub fn raw_query_items( &self ) -> Option> + DoubleEndedIterator + Clone> { let query = self.uri.query()?; self.state.query_items.as_ref().map(move |items| { items.iter().map(move |item| item.convert(query)) }) } /// Set `self`'s parameters given that the route used to reach this request /// was `route`. Use during routing when attempting a given route. #[inline(always)] pub(crate) fn set_route(&self, route: &'r Route) { self.state.route.set(Some(route)); } /// Set the method of `self`, even when `self` is a shared reference. Used /// during routing to override methods for re-routing. #[inline(always)] pub(crate) fn _set_method(&self, method: Method) { self.method.set(method); } /// Convert from Hyper types into a Rocket Request. pub(crate) fn from_hyp( rocket: &'r Rocket, h_method: hyper::Method, h_headers: hyper::header::Headers, h_uri: hyper::RequestUri, h_addr: SocketAddr, ) -> Result, String> { // Get a copy of the URI for later use. let uri = match h_uri { hyper::RequestUri::AbsolutePath(s) => s, _ => return Err(format!("Bad URI: {}", h_uri)), }; // Ensure that the method is known. TODO: Allow made-up methods? let method = match Method::from_hyp(&h_method) { Some(method) => method, None => return Err(format!("Invalid method: {}", h_method)) }; // We need to re-parse the URI since we don't trust Hyper... :( let uri = Origin::parse_owned(uri).map_err(|e| e.to_string())?; // Construct the request object. let mut request = Request::new(rocket, method, uri); request.set_remote(h_addr); // Set the request cookies, if they exist. if let Some(cookie_headers) = h_headers.get_raw("Cookie") { let mut cookie_jar = CookieJar::new(); for header in cookie_headers { let raw_str = match std::str::from_utf8(header) { Ok(string) => string, Err(_) => continue }; for cookie_str in raw_str.split(';').map(|s| s.trim()) { if let Some(cookie) = Cookies::parse_cookie(cookie_str) { cookie_jar.add_original(cookie); } } } request.state.cookies = RefCell::new(cookie_jar); } // Set the rest of the headers. for hyp in h_headers.iter() { if let Some(header_values) = h_headers.get_raw(hyp.name()) { for value in header_values { // This is not totally correct since values needn't be UTF8. let value_str = String::from_utf8_lossy(value).into_owned(); let header = Header::new(hyp.name().to_string(), value_str); request.add_header(header); } } } Ok(request) } } impl fmt::Debug for Request<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Request") .field("method", &self.method) .field("uri", &self.uri) .field("headers", &self.headers()) .field("remote", &self.remote()) .finish() } } impl fmt::Display for Request<'_> { /// Pretty prints a Request. This is primarily used by Rocket's logging /// infrastructure. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{} {}", Paint::green(self.method()), Paint::blue(&self.uri))?; // Print the requests media type when the route specifies a format. if let Some(media_type) = self.format() { if !media_type.is_any() { write!(f, " {}", Paint::yellow(media_type))?; } } Ok(()) } } impl IndexedFormItem { #[inline(always)] fn from(s: &str, i: FormItem<'_>) -> Self { let (r, k, v) = (indices(i.raw, s), indices(i.key, s), indices(i.value, s)); IndexedFormItem { raw: r, key: k, value: v } } #[inline(always)] fn convert<'s>(&self, source: &'s str) -> FormItem<'s> { FormItem { raw: source[self.raw.0..self.raw.1].into(), key: source[self.key.0..self.key.1].into(), value: source[self.value.0..self.value.1].into(), } } } fn indices(needle: &str, haystack: &str) -> (usize, usize) { Indexed::checked_from(needle, haystack) .expect("segments inside of path/query") .indices() }