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}