rama_http/service/
redirect.rs1use crate::Request;
4use crate::{header, HeaderValue, Response, StatusCode, Uri};
5use rama_core::{Context, Service};
6use std::{
7 convert::{Infallible, TryFrom},
8 fmt,
9 marker::PhantomData,
10};
11
12pub struct Redirect<ResBody> {
14 status_code: StatusCode,
15 location: HeaderValue,
16 _marker: PhantomData<fn() -> ResBody>,
18}
19
20impl<ResBody> Redirect<ResBody> {
21 pub fn temporary(uri: Uri) -> Self {
25 Self::with_status_code(StatusCode::TEMPORARY_REDIRECT, uri)
26 }
27
28 pub fn permanent(uri: Uri) -> Self {
32 Self::with_status_code(StatusCode::PERMANENT_REDIRECT, uri)
33 }
34
35 pub fn with_status_code(status_code: StatusCode, uri: Uri) -> Self {
44 assert!(
45 status_code.is_redirection(),
46 "not a redirection status code"
47 );
48
49 Self {
50 status_code,
51 location: HeaderValue::try_from(uri.to_string())
52 .expect("URI isn't a valid header value"),
53 _marker: PhantomData,
54 }
55 }
56}
57
58impl<State, Body, ResBody> Service<State, Request<Body>> for Redirect<ResBody>
59where
60 State: Clone + Send + Sync + 'static,
61 Body: Send + 'static,
62 ResBody: Default + Send + 'static,
63{
64 type Response = Response<ResBody>;
65 type Error = Infallible;
66
67 async fn serve(
68 &self,
69 _ctx: Context<State>,
70 _req: Request<Body>,
71 ) -> Result<Self::Response, Self::Error> {
72 let mut res = Response::default();
73 *res.status_mut() = self.status_code;
74 res.headers_mut()
75 .insert(header::LOCATION, self.location.clone());
76 Ok(res)
77 }
78}
79
80impl<ResBody> fmt::Debug for Redirect<ResBody> {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 f.debug_struct("Redirect")
83 .field("status_code", &self.status_code)
84 .field("location", &self.location)
85 .finish()
86 }
87}
88
89impl<ResBody> Clone for Redirect<ResBody> {
90 fn clone(&self) -> Self {
91 Self {
92 status_code: self.status_code,
93 location: self.location.clone(),
94 _marker: PhantomData,
95 }
96 }
97}