@@ -2,7 +2,7 @@ use super::cache::CachePolicy;
22use crate :: {
33 db:: Pool ,
44 utils:: spawn_blocking,
5- web:: { error:: AxumResult , match_version_axum} ,
5+ web:: { axum_redirect , error:: AxumResult , match_version_axum, MatchSemver } ,
66} ;
77use axum:: {
88 extract:: { Extension , Path } ,
@@ -21,10 +21,18 @@ pub(crate) async fn status_handler(
2121 // We use an async block to emulate a try block so that we can apply the above CORS header
2222 // and cache policy to both successful and failed responses
2323 async move {
24- let ( version, id) = match_version_axum ( & pool, & name, Some ( & req_version) )
24+ let ( version, id) = match match_version_axum ( & pool, & name, Some ( & req_version) )
2525 . await ?
2626 . exact_name_only ( ) ?
27- . into_parts ( ) ;
27+ {
28+ MatchSemver :: Exact ( ( version, id) ) | MatchSemver :: Latest ( ( version, id) ) => {
29+ ( version, id)
30+ }
31+ MatchSemver :: Semver ( ( version, _) ) => {
32+ let redirect = axum_redirect ( format ! ( "/crate/{name}/{version}/status.json" ) ) ?;
33+ return Ok ( redirect. into_response ( ) ) ;
34+ }
35+ } ;
2836
2937 let rustdoc_status: bool = spawn_blocking ( {
3038 move || {
@@ -42,10 +50,12 @@ pub(crate) async fn status_handler(
4250 } )
4351 . await ?;
4452
45- AxumResult :: Ok ( Json ( serde_json:: json!( {
53+ let json = Json ( serde_json:: json!( {
4654 "version" : version,
4755 "doc_status" : rustdoc_status,
48- } ) ) )
56+ } ) ) ;
57+
58+ AxumResult :: Ok ( json. into_response ( ) )
4959 }
5060 . await ,
5161 )
@@ -54,7 +64,7 @@ pub(crate) async fn status_handler(
5464#[ cfg( test) ]
5565mod tests {
5666 use crate :: {
57- test:: { assert_cache_control, wrapper} ,
67+ test:: { assert_cache_control, assert_redirect , wrapper} ,
5868 web:: cache:: CachePolicy ,
5969 } ;
6070 use reqwest:: StatusCode ;
@@ -63,6 +73,7 @@ mod tests {
6373 #[ test_case( "latest" ) ]
6474 #[ test_case( "0.1" ) ]
6575 #[ test_case( "0.1.0" ) ]
76+ #[ test_case( "=0.1.0" ; "exact_version" ) ]
6677 fn status ( version : & str ) {
6778 wrapper ( |env| {
6879 env. fake_release ( ) . name ( "foo" ) . version ( "0.1.0" ) . create ( ) ?;
@@ -88,9 +99,28 @@ mod tests {
8899 } ) ;
89100 }
90101
102+ #[ test_case( "0.1" ) ]
103+ #[ test_case( "*" ) ]
104+ fn redirect ( version : & str ) {
105+ wrapper ( |env| {
106+ env. fake_release ( ) . name ( "foo" ) . version ( "0.1.0" ) . create ( ) ?;
107+
108+ let redirect = assert_redirect (
109+ & format ! ( "/crate/foo/{version}/status.json" ) ,
110+ "/crate/foo/0.1.0/status.json" ,
111+ env. frontend ( ) ,
112+ ) ?;
113+ assert_cache_control ( & redirect, CachePolicy :: NoStoreMustRevalidate , & env. config ( ) ) ;
114+ assert_eq ! ( redirect. headers( ) [ "access-control-allow-origin" ] , "*" ) ;
115+
116+ Ok ( ( ) )
117+ } ) ;
118+ }
119+
91120 #[ test_case( "latest" ) ]
92121 #[ test_case( "0.1" ) ]
93122 #[ test_case( "0.1.0" ) ]
123+ #[ test_case( "=0.1.0" ; "exact_version" ) ]
94124 fn failure ( version : & str ) {
95125 wrapper ( |env| {
96126 env. fake_release ( )
@@ -124,14 +154,15 @@ mod tests {
124154 #[ test_case( "bar" , "0.1" ) ]
125155 #[ test_case( "bar" , "0.1.0" ) ]
126156 // version not found
157+ #[ test_case( "foo" , "=0.1.0" ; "exact_version" ) ]
127158 #[ test_case( "foo" , "0.2" ) ]
128159 #[ test_case( "foo" , "0.2.0" ) ]
129160 // invalid semver
130161 #[ test_case( "foo" , "0,1" ) ]
131162 #[ test_case( "foo" , "0,1,0" ) ]
132163 fn not_found ( krate : & str , version : & str ) {
133164 wrapper ( |env| {
134- env. fake_release ( ) . name ( "foo" ) . version ( "0.1.0 " ) . create ( ) ?;
165+ env. fake_release ( ) . name ( "foo" ) . version ( "0.1.1 " ) . create ( ) ?;
135166
136167 let response = env
137168 . frontend ( )
0 commit comments