@@ -118,13 +118,32 @@ async fn returns_404_if_file_not_found() {
118
118
119
119
#[ tokio:: test]
120
120
async fn redirects_if_trailing_slash_is_missing ( ) {
121
- let harness = Harness :: new ( vec ! [ ( "dir /index.html" , "this is index" ) ] ) ;
121
+ let harness = Harness :: new ( vec ! [ ( "foo/bar /index.html" , "this is index" ) ] ) ;
122
122
123
- let res = harness. get ( "/dir " ) . await . unwrap ( ) ;
123
+ let res = harness. get ( "/foo/bar " ) . await . unwrap ( ) ;
124
124
assert_eq ! ( res. status( ) , StatusCode :: MOVED_PERMANENTLY ) ;
125
125
126
126
let url = res. headers ( ) . get ( header:: LOCATION ) . unwrap ( ) ;
127
- assert_eq ! ( url, "/dir/" ) ;
127
+ assert_eq ! ( url, "/foo/bar/" ) ;
128
+ }
129
+
130
+ #[ tokio:: test]
131
+ async fn redirects_to_sanitized_path ( ) {
132
+ let harness = Harness :: new ( vec ! [ ( "foo.org/bar/index.html" , "this is index" ) ] ) ;
133
+
134
+ // Previous versions would base the redirect on the request path, but that is user input, and
135
+ // the user could construct a schema-relative redirect this way.
136
+ let res = harness. get ( "//foo.org/bar" ) . await . unwrap ( ) ;
137
+ assert_eq ! ( res. status( ) , StatusCode :: MOVED_PERMANENTLY ) ;
138
+
139
+ let url = res. headers ( ) . get ( header:: LOCATION ) . unwrap ( ) ;
140
+ // TODO: The request path is apparently parsed differently on Windows, but at least the
141
+ // resulting redirect is still safe, and that's the important part.
142
+ if cfg ! ( target_os = "windows" ) {
143
+ assert_eq ! ( url, "/" ) ;
144
+ } else {
145
+ assert_eq ! ( url, "/foo.org/bar/" ) ;
146
+ }
128
147
}
129
148
130
149
#[ tokio:: test]
0 commit comments