diff --git a/Cargo.toml b/Cargo.toml index e7579bfa7f..a2c6936394 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ type_complexity = "allow" await_holding_lock = "warn" dbg_macro = "warn" -empty_enums = "warn" +empty_enum = "warn" enum_glob_use = "warn" equatable_if_let = "warn" exit = "warn" diff --git a/axum-core/src/response/into_response_parts.rs b/axum-core/src/response/into_response_parts.rs index a142b50bed..95205398f0 100644 --- a/axum-core/src/response/into_response_parts.rs +++ b/axum-core/src/response/into_response_parts.rs @@ -127,6 +127,11 @@ impl ResponseParts { pub fn extensions_mut(&mut self) -> &mut Extensions { self.res.extensions_mut() } + + /// Set the status code of the response. + pub fn set_status(&mut self, status: StatusCode) { + *self.res.status_mut() = status; + } } impl IntoResponseParts for HeaderMap { diff --git a/axum/src/response/redirect.rs b/axum/src/response/redirect.rs index 696430f803..c21cc505ee 100644 --- a/axum/src/response/redirect.rs +++ b/axum/src/response/redirect.rs @@ -1,4 +1,4 @@ -use axum_core::response::{IntoResponse, Response}; +use axum_core::response::{IntoResponse, IntoResponseParts, Response, ResponseParts}; use http::{header::LOCATION, HeaderValue, StatusCode}; /// Response that redirects the request to another location. @@ -93,8 +93,28 @@ impl IntoResponse for Redirect { } } +impl IntoResponseParts for Redirect { + type Error = Response; + + fn into_response_parts(self, mut res: ResponseParts) -> Result { + match HeaderValue::try_from(self.location) { + Ok(location) => { + res.set_status(self.status_code); + res.headers_mut().insert(LOCATION, location); + Ok(res) + } + Err(error) => { + // If the URI is invalid, we return a 500 error response immediately + Err((StatusCode::INTERNAL_SERVER_ERROR, error.to_string()).into_response()) + } + } + } +} + #[cfg(test)] mod tests { + use crate::response::Html; + use super::Redirect; use axum_core::response::IntoResponse; use http::StatusCode; @@ -135,4 +155,18 @@ mod tests { assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR); } + + #[test] + fn as_response_parts() { + let response = ( + Redirect::to(EXAMPLE_URL), + Html(format!( + r#"

Redirecting to {EXAMPLE_URL}

"# + )), + ) + .into_response(); + + assert_eq!(response.status(), StatusCode::SEE_OTHER); + assert_eq!(response.headers()[http::header::LOCATION], EXAMPLE_URL); + } }