[go: up one dir, main page]

tide/
request.rs

1use async_std::io::{self, prelude::*};
2use async_std::task::{Context, Poll};
3use route_recognizer::Params;
4
5use std::ops::Index;
6use std::pin::Pin;
7
8#[cfg(feature = "cookies")]
9use crate::cookies::CookieData;
10#[cfg(feature = "cookies")]
11use crate::http::cookies::Cookie;
12use crate::http::format_err;
13use crate::http::headers::{self, HeaderName, HeaderValues, ToHeaderValues};
14use crate::http::{self, Body, Method, Mime, StatusCode, Url, Version};
15use crate::Response;
16
17pin_project_lite::pin_project! {
18    /// An HTTP request.
19    ///
20    /// The `Request` gives endpoints access to basic information about the incoming
21    /// request, route parameters, and various ways of accessing the request's body.
22    ///
23    /// Requests also provide *extensions*, a type map primarily used for low-level
24    /// communication between middleware and endpoints.
25    #[derive(Debug)]
26    pub struct Request<State> {
27        pub(crate) state: State,
28        #[pin]
29        pub(crate) req: http::Request,
30        pub(crate) route_params: Vec<Params>,
31    }
32}
33
34impl<State> Request<State> {
35    /// Create a new `Request`.
36    pub(crate) fn new(state: State, req: http_types::Request, route_params: Vec<Params>) -> Self {
37        Self {
38            state,
39            req,
40            route_params,
41        }
42    }
43
44    /// Access the request's HTTP method.
45    ///
46    /// # Examples
47    ///
48    /// ```no_run
49    /// # use async_std::task::block_on;
50    /// # fn main() -> Result<(), std::io::Error> { block_on(async {
51    /// #
52    /// use tide::Request;
53    ///
54    /// let mut app = tide::new();
55    /// app.at("/").get(|req: Request<()>| async move {
56    ///     assert_eq!(req.method(), http_types::Method::Get);
57    ///     Ok("")
58    /// });
59    /// app.listen("127.0.0.1:8080").await?;
60    /// #
61    /// # Ok(()) })}
62    /// ```
63    #[must_use]
64    pub fn method(&self) -> Method {
65        self.req.method()
66    }
67
68    /// Access the request's full URI method.
69    ///
70    /// # Examples
71    ///
72    /// ```no_run
73    /// # use async_std::task::block_on;
74    /// # fn main() -> Result<(), std::io::Error> { block_on(async {
75    /// #
76    /// use tide::Request;
77    ///
78    /// let mut app = tide::new();
79    /// app.at("/").get(|req: Request<()>| async move {
80    ///     assert_eq!(req.url(), &"/".parse::<tide::http::Url>().unwrap());
81    ///     Ok("")
82    /// });
83    /// app.listen("127.0.0.1:8080").await?;
84    /// #
85    /// # Ok(()) })}
86    /// ```
87    #[must_use]
88    pub fn url(&self) -> &Url {
89        self.req.url()
90    }
91
92    /// Access the request's HTTP version.
93    ///
94    /// # Examples
95    ///
96    /// ```no_run
97    /// # use async_std::task::block_on;
98    /// # fn main() -> Result<(), std::io::Error> { block_on(async {
99    /// #
100    /// use tide::Request;
101    ///
102    /// let mut app = tide::new();
103    /// app.at("/").get(|req: Request<()>| async move {
104    ///     assert_eq!(req.version(), Some(http_types::Version::Http1_1));
105    ///     Ok("")
106    /// });
107    /// app.listen("127.0.0.1:8080").await?;
108    /// #
109    /// # Ok(()) })}
110    /// ```
111    #[must_use]
112    pub fn version(&self) -> Option<Version> {
113        self.req.version()
114    }
115
116    /// Get the peer socket address for the underlying transport, if
117    /// that information is available for this request.
118    #[must_use]
119    pub fn peer_addr(&self) -> Option<&str> {
120        self.req.peer_addr()
121    }
122
123    /// Get the local socket address for the underlying transport, if
124    /// that information is available for this request.
125    #[must_use]
126    pub fn local_addr(&self) -> Option<&str> {
127        self.req.local_addr()
128    }
129
130    /// Get the remote address for this request.
131    ///
132    /// This is determined in the following priority:
133    /// 1. `Forwarded` header `for` key
134    /// 2. The first `X-Forwarded-For` header
135    /// 3. Peer address of the transport
136    #[must_use]
137    pub fn remote(&self) -> Option<&str> {
138        self.req.remote()
139    }
140
141    /// Get the destination host for this request.
142    ///
143    /// This is determined in the following priority:
144    /// 1. `Forwarded` header `host` key
145    /// 2. The first `X-Forwarded-Host` header
146    /// 3. `Host` header
147    /// 4. URL domain, if any
148    #[must_use]
149    pub fn host(&self) -> Option<&str> {
150        self.req.host()
151    }
152
153    /// Get the request content type as a `Mime`.
154    ///
155    /// This gets the request `Content-Type` header.
156    ///
157    /// [Read more on MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types)
158    #[must_use]
159    pub fn content_type(&self) -> Option<Mime> {
160        self.req.content_type()
161    }
162
163    /// Get an HTTP header.
164    ///
165    /// # Examples
166    ///
167    /// ```no_run
168    /// # use async_std::task::block_on;
169    /// # fn main() -> Result<(), std::io::Error> { block_on(async {
170    /// #
171    /// use tide::Request;
172    ///
173    /// let mut app = tide::new();
174    /// app.at("/").get(|req: Request<()>| async move {
175    ///     assert_eq!(req.header("X-Forwarded-For").unwrap(), "127.0.0.1");
176    ///     Ok("")
177    /// });
178    /// app.listen("127.0.0.1:8080").await?;
179    /// #
180    /// # Ok(()) })}
181    /// ```
182    #[must_use]
183    pub fn header(
184        &self,
185        key: impl Into<http_types::headers::HeaderName>,
186    ) -> Option<&http_types::headers::HeaderValues> {
187        self.req.header(key)
188    }
189
190    /// Get a mutable reference to a header.
191    pub fn header_mut(&mut self, name: impl Into<HeaderName>) -> Option<&mut HeaderValues> {
192        self.req.header_mut(name)
193    }
194
195    /// Set an HTTP header.
196    pub fn insert_header(
197        &mut self,
198        name: impl Into<HeaderName>,
199        values: impl ToHeaderValues,
200    ) -> Option<HeaderValues> {
201        self.req.insert_header(name, values)
202    }
203
204    /// Append a header to the headers.
205    ///
206    /// Unlike `insert` this function will not override the contents of a header, but insert a
207    /// header if there aren't any. Or else append to the existing list of headers.
208    pub fn append_header(&mut self, name: impl Into<HeaderName>, values: impl ToHeaderValues) {
209        self.req.append_header(name, values)
210    }
211
212    /// Remove a header.
213    pub fn remove_header(&mut self, name: impl Into<HeaderName>) -> Option<HeaderValues> {
214        self.req.remove_header(name)
215    }
216
217    /// An iterator visiting all header pairs in arbitrary order.
218    #[must_use]
219    pub fn iter(&self) -> headers::Iter<'_> {
220        self.req.iter()
221    }
222
223    /// An iterator visiting all header pairs in arbitrary order, with mutable references to the
224    /// values.
225    #[must_use]
226    pub fn iter_mut(&mut self) -> headers::IterMut<'_> {
227        self.req.iter_mut()
228    }
229
230    /// An iterator visiting all header names in arbitrary order.
231    #[must_use]
232    pub fn header_names(&self) -> headers::Names<'_> {
233        self.req.header_names()
234    }
235
236    /// An iterator visiting all header values in arbitrary order.
237    #[must_use]
238    pub fn header_values(&self) -> headers::Values<'_> {
239        self.req.header_values()
240    }
241
242    /// Get a request extension value.
243    #[must_use]
244    pub fn ext<T: Send + Sync + 'static>(&self) -> Option<&T> {
245        self.req.ext().get()
246    }
247
248    /// Get a mutable reference to value stored in request extensions.
249    #[must_use]
250    pub fn ext_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
251        self.req.ext_mut().get_mut()
252    }
253
254    /// Set a request extension value.
255    pub fn set_ext<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
256        self.req.ext_mut().insert(val)
257    }
258
259    #[must_use]
260    ///  Access application scoped state.
261    pub fn state(&self) -> &State {
262        &self.state
263    }
264
265    /// Extract and parse a route parameter by name.
266    ///
267    /// Returns the parameter as a `&str`, borrowed from this `Request`.
268    ///
269    /// The name should *not* include the leading `:` or the trailing `*` (if
270    /// any).
271    ///
272    /// # Errors
273    ///
274    /// An error is returned if `key` is not a valid parameter for the route.
275    ///
276    /// # Examples
277    ///
278    /// ```no_run
279    /// # use async_std::task::block_on;
280    /// # fn main() -> Result<(), std::io::Error> { block_on(async {
281    /// #
282    /// use tide::{Request, Result};
283    ///
284    /// async fn greet(req: Request<()>) -> Result<String> {
285    ///     let name = req.param("name").unwrap_or("world");
286    ///     Ok(format!("Hello, {}!", name))
287    /// }
288    ///
289    /// let mut app = tide::new();
290    /// app.at("/hello").get(greet);
291    /// app.at("/hello/:name").get(greet);
292    /// app.listen("127.0.0.1:8080").await?;
293    /// #
294    /// # Ok(()) })}
295    /// ```
296    pub fn param(&self, key: &str) -> crate::Result<&str> {
297        self.route_params
298            .iter()
299            .rev()
300            .find_map(|params| params.find(key))
301            .ok_or_else(|| format_err!("Param \"{}\" not found", key.to_string()))
302    }
303
304    /// Parse the URL query component into a struct, using [serde_qs](https://docs.rs/serde_qs). To
305    /// get the entire query as an unparsed string, use `request.url().query()`
306    ///
307    /// ```rust
308    /// # fn main() -> Result<(), std::io::Error> { async_std::task::block_on(async {
309    /// use tide::prelude::*;
310    /// let mut app = tide::new();
311    ///
312    /// #[derive(Deserialize)]
313    /// #[serde(default)]
314    /// struct Page {
315    ///     size: u8,
316    ///     offset: u8,
317    /// }
318    /// impl Default for Page {
319    ///     fn default() -> Self {
320    ///         Self {
321    ///             size: 25,
322    ///             offset: 0,
323    ///         }
324    ///     }
325    /// }
326    /// app.at("/pages").post(|req: tide::Request<()>| async move {
327    ///     let page: Page = req.query()?;
328    ///     Ok(format!("page {}, with {} items", page.offset, page.size))
329    /// });
330    ///
331    /// # if false {
332    /// app.listen("localhost:8000").await?;
333    /// # }
334    ///
335    /// // $ curl localhost:8000/pages
336    /// // page 0, with 25 items
337    ///
338    /// // $ curl localhost:8000/pages?offset=1
339    /// // page 1, with 25 items
340    ///
341    /// // $ curl localhost:8000/pages?offset=2&size=50
342    /// // page 2, with 50 items
343    ///
344    /// // $ curl localhost:8000/pages?size=5000
345    /// // failed with reason: number too large to fit in target type
346    ///
347    /// // $ curl localhost:8000/pages?size=all
348    /// // failed with reason: invalid digit found in string
349    /// # Ok(()) })}
350    /// ```
351
352    pub fn query<T: serde::de::DeserializeOwned>(&self) -> crate::Result<T> {
353        self.req.query()
354    }
355
356    /// Set the body reader.
357    pub fn set_body(&mut self, body: impl Into<Body>) {
358        self.req.set_body(body)
359    }
360
361    /// Take the request body as a `Body`.
362    ///
363    /// This method can be called after the body has already been taken or read,
364    /// but will return an empty `Body`.
365    ///
366    /// This is useful for consuming the body via an AsyncReader or AsyncBufReader.
367    pub fn take_body(&mut self) -> Body {
368        self.req.take_body()
369    }
370
371    /// Reads the entire request body into a byte buffer.
372    ///
373    /// This method can be called after the body has already been read, but will
374    /// produce an empty buffer.
375    ///
376    /// # Errors
377    ///
378    /// Any I/O error encountered while reading the body is immediately returned
379    /// as an `Err`.
380    ///
381    /// # Examples
382    ///
383    /// ```no_run
384    /// # use async_std::task::block_on;
385    /// # fn main() -> Result<(), std::io::Error> { block_on(async {
386    /// #
387    /// use tide::Request;
388    ///
389    /// let mut app = tide::new();
390    /// app.at("/").get(|mut req: Request<()>| async move {
391    ///     let _body: Vec<u8> = req.body_bytes().await.unwrap();
392    ///     Ok("")
393    /// });
394    /// app.listen("127.0.0.1:8080").await?;
395    /// #
396    /// # Ok(()) })}
397    /// ```
398    pub async fn body_bytes(&mut self) -> crate::Result<Vec<u8>> {
399        let res = self.req.body_bytes().await?;
400        Ok(res)
401    }
402
403    /// Reads the entire request body into a string.
404    ///
405    /// This method can be called after the body has already been read, but will
406    /// produce an empty buffer.
407    ///
408    /// # Errors
409    ///
410    /// Any I/O error encountered while reading the body is immediately returned
411    /// as an `Err`.
412    ///
413    /// If the body cannot be interpreted as valid UTF-8, an `Err` is returned.
414    ///
415    /// # Examples
416    ///
417    /// ```no_run
418    /// # use async_std::task::block_on;
419    /// # fn main() -> Result<(), std::io::Error> { block_on(async {
420    /// #
421    /// use tide::Request;
422    ///
423    /// let mut app = tide::new();
424    /// app.at("/").get(|mut req: Request<()>| async move {
425    ///     let _body: String = req.body_string().await.unwrap();
426    ///     Ok("")
427    /// });
428    /// app.listen("127.0.0.1:8080").await?;
429    /// #
430    /// # Ok(()) })}
431    /// ```
432    pub async fn body_string(&mut self) -> crate::Result<String> {
433        let res = self.req.body_string().await?;
434        Ok(res)
435    }
436
437    /// Reads and deserialized the entire request body via json.
438    ///
439    /// # Errors
440    ///
441    /// Any I/O error encountered while reading the body is immediately returned
442    /// as an `Err`.
443    ///
444    /// If the body cannot be interpreted as valid json for the target type `T`,
445    /// an `Err` is returned.
446    pub async fn body_json<T: serde::de::DeserializeOwned>(&mut self) -> crate::Result<T> {
447        let res = self.req.body_json().await?;
448        Ok(res)
449    }
450
451    /// Parse the request body as a form.
452    ///
453    /// ```rust
454    /// # fn main() -> Result<(), std::io::Error> { async_std::task::block_on(async {
455    /// use tide::prelude::*;
456    /// let mut app = tide::new();
457    ///
458    /// #[derive(Deserialize)]
459    /// struct Animal {
460    ///   name: String,
461    ///   legs: u8
462    /// }
463    ///
464    /// app.at("/").post(|mut req: tide::Request<()>| async move {
465    ///     let animal: Animal = req.body_form().await?;
466    ///     Ok(format!(
467    ///         "hello, {}! i've put in an order for {} shoes",
468    ///         animal.name, animal.legs
469    ///     ))
470    /// });
471    ///
472    /// # if false {
473    /// app.listen("localhost:8000").await?;
474    /// # }
475    ///
476    /// // $ curl localhost:8000/orders/shoes -d "name=chashu&legs=4"
477    /// // hello, chashu! i've put in an order for 4 shoes
478    ///
479    /// // $ curl localhost:8000/orders/shoes -d "name=mary%20millipede&legs=750"
480    /// // number too large to fit in target type
481    /// # Ok(()) })}
482    /// ```
483    pub async fn body_form<T: serde::de::DeserializeOwned>(&mut self) -> crate::Result<T> {
484        let res = self.req.body_form().await?;
485        Ok(res)
486    }
487
488    /// returns a `Cookie` by name of the cookie.
489    #[cfg(feature = "cookies")]
490    #[must_use]
491    pub fn cookie(&self, name: &str) -> Option<Cookie<'static>> {
492        self.ext::<CookieData>()
493            .and_then(|cookie_data| cookie_data.content.read().unwrap().get(name).cloned())
494    }
495
496    /// Retrieves a reference to the current session.
497    ///
498    /// # Panics
499    ///
500    /// This method will panic if a tide::sessions:SessionMiddleware has not
501    /// been run.
502    #[cfg(feature = "sessions")]
503    pub fn session(&self) -> &crate::sessions::Session {
504        self.ext::<crate::sessions::Session>().expect(
505            "request session not initialized, did you enable tide::sessions::SessionMiddleware?",
506        )
507    }
508
509    /// Retrieves a mutable reference to the current session.
510    ///
511    /// # Panics
512    ///
513    /// This method will panic if a tide::sessions:SessionMiddleware has not
514    /// been run.
515    #[cfg(feature = "sessions")]
516    pub fn session_mut(&mut self) -> &mut crate::sessions::Session {
517        self.ext_mut().expect(
518            "request session not initialized, did you enable tide::sessions::SessionMiddleware?",
519        )
520    }
521
522    /// Get the length of the body stream, if it has been set.
523    ///
524    /// This value is set when passing a fixed-size object into as the body. E.g. a string, or a
525    /// buffer. Consumers of this API should check this value to decide whether to use `Chunked`
526    /// encoding, or set the response length.
527    #[must_use]
528    pub fn len(&self) -> Option<usize> {
529        self.req.len()
530    }
531
532    /// Returns `true` if the request has a set body stream length of zero, `false` otherwise.
533    #[must_use]
534    pub fn is_empty(&self) -> Option<bool> {
535        Some(self.req.len()? == 0)
536    }
537}
538
539impl<State> AsRef<http::Request> for Request<State> {
540    fn as_ref(&self) -> &http::Request {
541        &self.req
542    }
543}
544
545impl<State> AsMut<http::Request> for Request<State> {
546    fn as_mut(&mut self) -> &mut http::Request {
547        &mut self.req
548    }
549}
550
551impl<State> AsRef<http::Headers> for Request<State> {
552    fn as_ref(&self) -> &http::Headers {
553        self.req.as_ref()
554    }
555}
556
557impl<State> AsMut<http::Headers> for Request<State> {
558    fn as_mut(&mut self) -> &mut http::Headers {
559        self.req.as_mut()
560    }
561}
562
563impl<State> Read for Request<State> {
564    fn poll_read(
565        self: Pin<&mut Self>,
566        cx: &mut Context<'_>,
567        buf: &mut [u8],
568    ) -> Poll<io::Result<usize>> {
569        self.project().req.poll_read(cx, buf)
570    }
571}
572
573impl<State> Into<http::Request> for Request<State> {
574    fn into(self) -> http::Request {
575        self.req
576    }
577}
578
579impl<State: Default> Into<Request<State>> for http_types::Request {
580    fn into(self) -> Request<State> {
581        Request::new(State::default(), self, Vec::<Params>::new())
582    }
583}
584
585// NOTE: From cannot be implemented for this conversion because `State` needs to
586// be constrained by a type.
587impl<State: Clone + Send + Sync + 'static> Into<Response> for Request<State> {
588    fn into(mut self) -> Response {
589        let mut res = Response::new(StatusCode::Ok);
590        res.set_body(self.take_body());
591        res
592    }
593}
594
595impl<State> IntoIterator for Request<State> {
596    type Item = (HeaderName, HeaderValues);
597    type IntoIter = http_types::headers::IntoIter;
598
599    /// Returns a iterator of references over the remaining items.
600    #[inline]
601    fn into_iter(self) -> Self::IntoIter {
602        self.req.into_iter()
603    }
604}
605
606impl<'a, State> IntoIterator for &'a Request<State> {
607    type Item = (&'a HeaderName, &'a HeaderValues);
608    type IntoIter = http_types::headers::Iter<'a>;
609
610    #[inline]
611    fn into_iter(self) -> Self::IntoIter {
612        self.req.iter()
613    }
614}
615
616impl<'a, State> IntoIterator for &'a mut Request<State> {
617    type Item = (&'a HeaderName, &'a mut HeaderValues);
618    type IntoIter = http_types::headers::IterMut<'a>;
619
620    #[inline]
621    fn into_iter(self) -> Self::IntoIter {
622        self.req.iter_mut()
623    }
624}
625
626impl<State> Index<HeaderName> for Request<State> {
627    type Output = HeaderValues;
628
629    /// Returns a reference to the value corresponding to the supplied name.
630    ///
631    /// # Panics
632    ///
633    /// Panics if the name is not present in `Request`.
634    #[inline]
635    fn index(&self, name: HeaderName) -> &HeaderValues {
636        &self.req[name]
637    }
638}
639
640impl<State> Index<&str> for Request<State> {
641    type Output = HeaderValues;
642
643    /// Returns a reference to the value corresponding to the supplied name.
644    ///
645    /// # Panics
646    ///
647    /// Panics if the name is not present in `Request`.
648    #[inline]
649    fn index(&self, name: &str) -> &HeaderValues {
650        &self.req[name]
651    }
652}
653
654pub(crate) fn rest(route_params: &[Params]) -> Option<&str> {
655    route_params
656        .last()
657        .and_then(|params| params.find("--tide-path-rest"))
658}