use super::{IntoResponse, Response};
use crate::body::{boxed, Empty};
use http::{header::LOCATION, HeaderValue, StatusCode, Uri};
use std::convert::TryFrom;
#[derive(Debug, Clone)]
pub struct Redirect {
status_code: StatusCode,
location: HeaderValue,
}
impl Redirect {
pub fn to(uri: Uri) -> Self {
Self::with_status_code(StatusCode::SEE_OTHER, uri)
}
pub fn temporary(uri: Uri) -> Self {
Self::with_status_code(StatusCode::TEMPORARY_REDIRECT, uri)
}
pub fn permanent(uri: Uri) -> Self {
Self::with_status_code(StatusCode::PERMANENT_REDIRECT, uri)
}
#[deprecated(
note = "This results in different behavior between clients, so Redirect::temporary or Redirect::to should be used instead"
)]
pub fn found(uri: Uri) -> Self {
Self::with_status_code(StatusCode::FOUND, uri)
}
fn with_status_code(status_code: StatusCode, uri: Uri) -> Self {
assert!(
status_code.is_redirection(),
"not a redirection status code"
);
Self {
status_code,
location: HeaderValue::try_from(uri.to_string())
.expect("URI isn't a valid header value"),
}
}
}
impl IntoResponse for Redirect {
fn into_response(self) -> Response {
let mut res = Response::new(boxed(Empty::new()));
*res.status_mut() = self.status_code;
res.headers_mut().insert(LOCATION, self.location);
res
}
}