Skip to content

Commit a41efa8

Browse files
committed
feat: add Redirect and deprecate new_redirect
1 parent 9d5976a commit a41efa8

2 files changed

Lines changed: 55 additions & 1 deletion

File tree

cot/src/response.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ pub trait ResponseExt: Sized + private::Sealed {
125125
/// * [`crate::reverse_redirect!`] – a more ergonomic way to create
126126
/// redirects to internal views
127127
#[must_use]
128+
#[deprecated(since = "0.5.0", note = "Use Redirect::new() instead")]
128129
fn new_redirect<T: Into<String>>(location: T) -> Self;
129130
}
130131

@@ -144,6 +145,58 @@ impl ResponseExt for Response {
144145
}
145146
}
146147

148+
/// A redirect response.
149+
///
150+
/// This type creates an HTTP redirect response with a status code of
151+
/// [`StatusCode::SEE_OTHER`] (303) and a `Location` header set to the
152+
/// specified URL.
153+
///
154+
/// # Examples
155+
///
156+
/// ```
157+
/// use cot::response::{IntoResponse, Redirect};
158+
///
159+
/// let response = Redirect::new("https://example.com");
160+
///
161+
/// assert_eq!(response.status(), cot::StatusCode::SEE_OTHER);
162+
/// ```
163+
///
164+
/// # See also
165+
///
166+
/// * [`crate::reverse_redirect!`] – a more ergonomic way to create redirects to
167+
/// internal views
168+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
169+
pub struct Redirect;
170+
171+
impl Redirect {
172+
/// Creates a new redirect response to the specified location.
173+
///
174+
/// The location can be any type that implements `Into<String>`, such as
175+
/// `&str`, `String`, or other string-like types.
176+
///
177+
/// # Panics
178+
///
179+
/// Panics if the provided location does not cast into
180+
/// [`http::HeaderValue`].
181+
///
182+
/// # Examples
183+
///
184+
/// ```
185+
/// use cot::response::Redirect;
186+
///
187+
/// let redirect = Redirect::new("/login");
188+
/// ```
189+
#[must_use]
190+
#[expect(clippy::new_ret_no_self)]
191+
pub fn new<T: Into<String>>(location: T) -> Response {
192+
http::Response::builder()
193+
.status(StatusCode::SEE_OTHER)
194+
.header(http::header::LOCATION, location.into())
195+
.body(Body::empty())
196+
.expect(RESPONSE_BUILD_FAILURE)
197+
}
198+
}
199+
147200
#[cfg(test)]
148201
mod tests {
149202
use super::*;
@@ -179,6 +232,7 @@ mod tests {
179232
}
180233

181234
#[test]
235+
#[expect(deprecated)]
182236
fn response_new_redirect() {
183237
let location = "http://example.com";
184238
let response = Response::new_redirect(location);

cot/src/router.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1022,7 +1022,7 @@ macro_rules! reverse_redirect {
10221022
$request,
10231023
$view_name,
10241024
$( $($key = $value),* )?
1025-
).map(|url| <$crate::response::Response as $crate::response::ResponseExt>::new_redirect(url))
1025+
).map($crate::response::Redirect::new)
10261026
};
10271027
}
10281028

0 commit comments

Comments
 (0)