3
3
use crate :: {
4
4
db:: Pool ,
5
5
impl_webpage,
6
- web:: { error:: Nope , file:: File as DbFile , page:: WebPage , MetaData } ,
6
+ web:: {
7
+ error:: Nope , file:: File as DbFile , match_version, page:: WebPage , redirect_base,
8
+ MatchSemver , MetaData , Url ,
9
+ } ,
7
10
Config , Storage ,
8
11
} ;
9
12
use iron:: { IronResult , Request , Response } ;
@@ -160,17 +163,42 @@ impl_webpage! {
160
163
161
164
pub fn source_browser_handler ( req : & mut Request ) -> IronResult < Response > {
162
165
let router = extension ! ( req, Router ) ;
163
- let name = cexpect ! ( req, router. find( "name" ) ) ;
164
- let version = cexpect ! ( req, router. find( "version" ) ) ;
166
+ let mut crate_name = cexpect ! ( req, router. find( "name" ) ) ;
167
+ let req_version = cexpect ! ( req, router. find( "version" ) ) ;
168
+ let pool = extension ! ( req, Pool ) ;
169
+ let mut conn = pool. get ( ) ?;
170
+
171
+ let mut req_path = req. url . path ( ) ;
172
+ // remove first elements from path which is /crate/:name/:version/source
173
+ req_path. drain ( 0 ..4 ) ;
174
+
175
+ let v = match_version ( & mut conn, & crate_name, Some ( req_version) ) ?;
176
+ if let Some ( new_name) = & v. corrected_name {
177
+ // `match_version` checked against -/_ typos, so if we have a name here we should
178
+ // use that instead
179
+ crate_name = new_name;
180
+ }
181
+ let version = match v. version {
182
+ MatchSemver :: Exact ( ( version, _) ) => version,
183
+ MatchSemver :: Semver ( ( version, _) ) => {
184
+ let url = ctry ! (
185
+ req,
186
+ Url :: parse( & format!(
187
+ "{}/crate/{}/{}/source/{}" ,
188
+ redirect_base( req) ,
189
+ crate_name,
190
+ version,
191
+ req_path. join( "/" ) ,
192
+ ) ) ,
193
+ ) ;
194
+
195
+ return Ok ( super :: redirect ( url) ) ;
196
+ }
197
+ } ;
165
198
166
199
// get path (req_path) for FileList::from_path and actual path for super::file::File::from_path
167
200
let ( req_path, file_path) = {
168
- let mut req_path = req. url . path ( ) ;
169
- // remove first elements from path which is /crate/:name/:version/source
170
- for _ in 0 ..4 {
171
- req_path. remove ( 0 ) ;
172
- }
173
- let file_path = format ! ( "sources/{}/{}/{}" , name, version, req_path. join( "/" ) ) ;
201
+ let file_path = format ! ( "sources/{}/{}/{}" , crate_name, version, req_path. join( "/" ) ) ;
174
202
175
203
// FileList::from_path is only working for directories
176
204
// remove file name if it's not a directory
@@ -183,13 +211,11 @@ pub fn source_browser_handler(req: &mut Request) -> IronResult<Response> {
183
211
// remove crate name and version from req_path
184
212
let path = req_path
185
213
. join ( "/" )
186
- . replace ( & format ! ( "{}/{}/" , name , version) , "" ) ;
214
+ . replace ( & format ! ( "{}/{}/" , crate_name , version) , "" ) ;
187
215
188
216
( path, file_path)
189
217
} ;
190
218
191
- let pool = extension ! ( req, Pool ) ;
192
- let mut conn = pool. get ( ) ?;
193
219
let storage = extension ! ( req, Storage ) ;
194
220
let config = extension ! ( req, Config ) ;
195
221
@@ -217,8 +243,8 @@ pub fn source_browser_handler(req: &mut Request) -> IronResult<Response> {
217
243
( None , false )
218
244
} ;
219
245
220
- let file_list =
221
- FileList :: from_path ( & mut conn , & name , & version , & req_path ) . ok_or ( Nope :: NoResults ) ?;
246
+ let file_list = FileList :: from_path ( & mut conn , & crate_name , & version , & req_path )
247
+ . ok_or ( Nope :: ResourceNotFound ) ?;
222
248
223
249
SourcePage {
224
250
file_list,
@@ -231,7 +257,7 @@ pub fn source_browser_handler(req: &mut Request) -> IronResult<Response> {
231
257
232
258
#[ cfg( test) ]
233
259
mod tests {
234
- use crate :: test:: { assert_success , wrapper } ;
260
+ use crate :: test:: * ;
235
261
236
262
#[ test]
237
263
fn cargo_ok_not_skipped ( ) {
@@ -247,4 +273,36 @@ mod tests {
247
273
Ok ( ( ) )
248
274
} ) ;
249
275
}
276
+
277
+ #[ test]
278
+ fn directory_not_found ( ) {
279
+ wrapper ( |env| {
280
+ env. fake_release ( )
281
+ . name ( "mbedtls" )
282
+ . version ( "0.2.0" )
283
+ . create ( ) ?;
284
+ let web = env. frontend ( ) ;
285
+ assert_not_found ( "/crate/mbedtls/0.2.0/source/test/" , web) ?;
286
+ Ok ( ( ) )
287
+ } )
288
+ }
289
+
290
+ #[ test]
291
+ fn semver_handled ( ) {
292
+ wrapper ( |env| {
293
+ env. fake_release ( )
294
+ . name ( "mbedtls" )
295
+ . version ( "0.2.0" )
296
+ . source_file ( "README.md" , b"hello" )
297
+ . create ( ) ?;
298
+ let web = env. frontend ( ) ;
299
+ assert_success ( "/crate/mbedtls/0.2.0/source/" , web) ?;
300
+ assert_redirect (
301
+ "/crate/mbedtls/*/source/" ,
302
+ "/crate/mbedtls/0.2.0/source/" ,
303
+ web,
304
+ ) ?;
305
+ Ok ( ( ) )
306
+ } )
307
+ }
250
308
}
0 commit comments