[go: up one dir, main page]

tide/
redirect.rs

1//! HTTP redirection endpoint.
2//!
3//! # Examples
4//!
5//! ```no_run
6//! # use async_std::task::block_on;
7//! # fn main() -> Result<(), std::io::Error> { block_on(async {
8//! #
9//! use tide::Redirect;
10//!
11//! let mut app = tide::new();
12//! app.at("/").get(|_| async { Ok("meow") });
13//! app.at("/nori").get(Redirect::temporary("/"));
14//! app.listen("127.0.0.1:8080").await?;
15//! #
16//! # Ok(()) }) }
17//! ```
18
19use crate::http::headers::LOCATION;
20use crate::StatusCode;
21use crate::{Endpoint, Request, Response};
22
23/// A redirection endpoint.
24///
25/// # Example
26///
27/// ```
28/// # use tide::{Response, Redirect, Request, StatusCode};
29/// # fn next_product() -> Option<String> { None }
30/// # #[allow(dead_code)]
31/// async fn route_handler(request: Request<()>) -> tide::Result {
32///     if let Some(product_url) = next_product() {
33///         Ok(Redirect::new(product_url).into())
34///     } else {
35///         //...
36/// #       Ok(Response::new(StatusCode::Ok)) //...
37///     }
38/// }
39/// ```
40#[derive(Debug, Clone)]
41pub struct Redirect<T: AsRef<str>> {
42    status: StatusCode,
43    location: T,
44}
45
46impl<T: AsRef<str>> Redirect<T> {
47    /// Creates an endpoint that represents a redirect to `location`.
48    ///
49    /// Uses status code 302 Found.
50    pub fn new(location: T) -> Self {
51        Self {
52            status: StatusCode::Found,
53            location,
54        }
55    }
56
57    /// Creates an endpoint that represents a permanent redirect to `location`.
58    ///
59    /// Uses status code 301 Permanent Redirect.
60    pub fn permanent(location: T) -> Self {
61        Self {
62            status: StatusCode::PermanentRedirect,
63            location,
64        }
65    }
66
67    /// Creates an endpoint that represents a temporary redirect to `location`.
68    ///
69    /// Uses status code 307 Temporary Redirect.
70    pub fn temporary(location: T) -> Self {
71        Self {
72            status: StatusCode::TemporaryRedirect,
73            location,
74        }
75    }
76
77    /// Creates an endpoint that represents a see other redirect to `location`.
78    ///
79    /// Uses status code 303 See Other.
80    pub fn see_other(location: T) -> Self {
81        Self {
82            status: StatusCode::SeeOther,
83            location,
84        }
85    }
86}
87
88#[async_trait::async_trait]
89impl<State, T> Endpoint<State> for Redirect<T>
90where
91    State: Clone + Send + Sync + 'static,
92    T: AsRef<str> + Send + Sync + 'static,
93{
94    async fn call(&self, _req: Request<State>) -> crate::Result<Response> {
95        Ok(self.into())
96    }
97}
98
99impl<T: AsRef<str>> Into<Response> for Redirect<T> {
100    fn into(self) -> Response {
101        (&self).into()
102    }
103}
104
105impl<T: AsRef<str>> Into<Response> for &Redirect<T> {
106    fn into(self) -> Response {
107        let mut res = Response::new(self.status);
108        res.insert_header(LOCATION, self.location.as_ref());
109        res
110    }
111}