1 //! Redirect requests to a new location.
2 //!
3 //! The types in this module are helpers that implement [`Reply`](Reply), and easy
4 //! to use in order to setup redirects.
5
6 use http::{header, StatusCode};
7
8 use self::sealed::AsLocation;
9 use crate::reply::{self, Reply};
10
11 /// A simple `301` redirect to a different location.
12 ///
13 /// # Example
14 ///
15 /// ```
16 /// use warp::{http::Uri, Filter};
17 ///
18 /// let route = warp::path("v1")
19 /// .map(|| {
20 /// warp::redirect(Uri::from_static("/v2"))
21 /// });
22 /// ```
redirect(uri: impl AsLocation) -> impl Reply23 pub fn redirect(uri: impl AsLocation) -> impl Reply {
24 reply::with_header(
25 StatusCode::MOVED_PERMANENTLY,
26 header::LOCATION,
27 uri.header_value(),
28 )
29 }
30
31 /// A simple `307` temporary redirect to a different location.
32 ///
33 /// # Example
34 ///
35 /// ```
36 /// use warp::{http::Uri, Filter};
37 ///
38 /// let route = warp::path("v1")
39 /// .map(|| {
40 /// warp::redirect::temporary(Uri::from_static("/v2"))
41 /// });
42 /// ```
temporary(uri: impl AsLocation) -> impl Reply43 pub fn temporary(uri: impl AsLocation) -> impl Reply {
44 reply::with_header(
45 StatusCode::TEMPORARY_REDIRECT,
46 header::LOCATION,
47 uri.header_value(),
48 )
49 }
50
51 mod sealed {
52 use bytes::Bytes;
53 use http::{header::HeaderValue, Uri};
54
55 // These sealed traits are to allow adding possibly new impls so other
56 // arguments could be accepted, like maybe just `warp::redirect("/v2")`.
57 pub trait AsLocation: Sealed {}
58 pub trait Sealed {
header_value(self) -> HeaderValue59 fn header_value(self) -> HeaderValue;
60 }
61
62 impl AsLocation for Uri {}
63
64 impl Sealed for Uri {
header_value(self) -> HeaderValue65 fn header_value(self) -> HeaderValue {
66 let bytes = Bytes::from(self.to_string());
67 HeaderValue::from_maybe_shared(bytes).expect("Uri is a valid HeaderValue")
68 }
69 }
70 }
71