@@ -21,7 +21,7 @@ use http::{header::LOCATION, HeaderValue, StatusCode};
21
21
#[ derive( Debug , Clone ) ]
22
22
pub struct Redirect {
23
23
status_code : StatusCode ,
24
- location : HeaderValue ,
24
+ location : String ,
25
25
}
26
26
27
27
impl Redirect {
@@ -33,10 +33,6 @@ impl Redirect {
33
33
/// body (if non-empty). If you want to preserve the request method and body,
34
34
/// [`Redirect::temporary`] should be used instead.
35
35
///
36
- /// # Panics
37
- ///
38
- /// If `uri` isn't a valid [`HeaderValue`].
39
- ///
40
36
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/303
41
37
pub fn to ( uri : & str ) -> Self {
42
38
Self :: with_status_code ( StatusCode :: SEE_OTHER , uri)
@@ -47,26 +43,28 @@ impl Redirect {
47
43
/// This has the same behavior as [`Redirect::to`], except it will preserve the original HTTP
48
44
/// method and body.
49
45
///
50
- /// # Panics
51
- ///
52
- /// If `uri` isn't a valid [`HeaderValue`].
53
- ///
54
46
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307
55
47
pub fn temporary ( uri : & str ) -> Self {
56
48
Self :: with_status_code ( StatusCode :: TEMPORARY_REDIRECT , uri)
57
49
}
58
50
59
51
/// Create a new [`Redirect`] that uses a [`308 Permanent Redirect`][mdn] status code.
60
52
///
61
- /// # Panics
62
- ///
63
- /// If `uri` isn't a valid [`HeaderValue`].
64
- ///
65
53
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/308
66
54
pub fn permanent ( uri : & str ) -> Self {
67
55
Self :: with_status_code ( StatusCode :: PERMANENT_REDIRECT , uri)
68
56
}
69
57
58
+ /// Returns the HTTP status code of the `Redirect`.
59
+ pub fn status_code ( & self ) -> StatusCode {
60
+ self . status_code
61
+ }
62
+
63
+ /// Returns the `Redirect`'s URI.
64
+ pub fn location ( & self ) -> & str {
65
+ & self . location
66
+ }
67
+
70
68
// This is intentionally not public since other kinds of redirects might not
71
69
// use the `Location` header, namely `304 Not Modified`.
72
70
//
@@ -79,13 +77,60 @@ impl Redirect {
79
77
80
78
Self {
81
79
status_code,
82
- location : HeaderValue :: try_from ( uri) . expect ( "URI isn't a valid header value" ) ,
80
+ location : uri. to_owned ( ) ,
83
81
}
84
82
}
85
83
}
86
84
87
85
impl IntoResponse for Redirect {
88
86
fn into_response ( self ) -> Response {
89
- ( self . status_code , [ ( LOCATION , self . location ) ] ) . into_response ( )
87
+ match HeaderValue :: try_from ( self . location ) {
88
+ Ok ( location) => ( self . status_code , [ ( LOCATION , location) ] ) . into_response ( ) ,
89
+ Err ( error) => ( StatusCode :: INTERNAL_SERVER_ERROR , error. to_string ( ) ) . into_response ( ) ,
90
+ }
91
+ }
92
+ }
93
+
94
+ #[ cfg( test) ]
95
+ mod tests {
96
+ use super :: Redirect ;
97
+ use axum_core:: response:: IntoResponse ;
98
+ use http:: StatusCode ;
99
+
100
+ const EXAMPLE_URL : & str = "https://example.com" ;
101
+
102
+ // Tests to make sure Redirect has the correct status codes
103
+ // based on the way it was constructed.
104
+ #[ test]
105
+ fn correct_status ( ) {
106
+ assert_eq ! (
107
+ StatusCode :: SEE_OTHER ,
108
+ Redirect :: to( EXAMPLE_URL ) . status_code( )
109
+ ) ;
110
+
111
+ assert_eq ! (
112
+ StatusCode :: TEMPORARY_REDIRECT ,
113
+ Redirect :: temporary( EXAMPLE_URL ) . status_code( )
114
+ ) ;
115
+
116
+ assert_eq ! (
117
+ StatusCode :: PERMANENT_REDIRECT ,
118
+ Redirect :: permanent( EXAMPLE_URL ) . status_code( )
119
+ ) ;
120
+ }
121
+
122
+ #[ test]
123
+ fn correct_location ( ) {
124
+ assert_eq ! ( EXAMPLE_URL , Redirect :: permanent( EXAMPLE_URL ) . location( ) ) ;
125
+
126
+ assert_eq ! ( "/redirect" , Redirect :: permanent( "/redirect" ) . location( ) )
127
+ }
128
+
129
+ #[ test]
130
+ fn test_internal_error ( ) {
131
+ let response = Redirect :: permanent ( "Axum is awesome, \n but newlines aren't allowed :(" )
132
+ . into_response ( ) ;
133
+
134
+ assert_eq ! ( response. status( ) , StatusCode :: INTERNAL_SERVER_ERROR ) ;
90
135
}
91
136
}
0 commit comments