Skip to content

Commit 707b8cb

Browse files
jyn514Joshua Nelson
authored and
Joshua Nelson
committed
Handle 404s and semver in source file viewer
1 parent 64200d4 commit 707b8cb

File tree

3 files changed

+81
-16
lines changed

3 files changed

+81
-16
lines changed

src/test/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ pub(crate) fn assert_success(path: &str, web: &TestFrontend) -> Result<(), Error
4747
Ok(())
4848
}
4949

50+
/// Make sure that a URL returns a 404
51+
pub(crate) fn assert_not_found(path: &str, web: &TestFrontend) -> Result<(), Error> {
52+
let status = web.get(path).send()?.status();
53+
assert_eq!(status, 404, "GET {} should have been a 404", path);
54+
Ok(())
55+
}
56+
5057
/// Make sure that a URL redirects to a specific page
5158
pub(crate) fn assert_redirect(
5259
path: &str,

src/web/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ macro_rules! ctry {
1616
let request: &::iron::Request = $req;
1717

1818
::log::error!(
19-
"called ctry!() on an `Err` value: {}\nnote: while attempting to fetch the route {:?}\n{:?}",
19+
"called ctry!() on an `Err` value: {:?}\nnote: while attempting to fetch the route {:?}\n{:?}",
2020
error,
2121
request.url,
2222
::backtrace::Backtrace::new(),

src/web/source.rs

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
use crate::{
44
db::Pool,
55
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+
},
710
Config, Storage,
811
};
912
use iron::{IronResult, Request, Response};
@@ -160,17 +163,42 @@ impl_webpage! {
160163

161164
pub fn source_browser_handler(req: &mut Request) -> IronResult<Response> {
162165
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+
};
165198

166199
// get path (req_path) for FileList::from_path and actual path for super::file::File::from_path
167200
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("/"));
174202

175203
// FileList::from_path is only working for directories
176204
// remove file name if it's not a directory
@@ -183,13 +211,11 @@ pub fn source_browser_handler(req: &mut Request) -> IronResult<Response> {
183211
// remove crate name and version from req_path
184212
let path = req_path
185213
.join("/")
186-
.replace(&format!("{}/{}/", name, version), "");
214+
.replace(&format!("{}/{}/", crate_name, version), "");
187215

188216
(path, file_path)
189217
};
190218

191-
let pool = extension!(req, Pool);
192-
let mut conn = pool.get()?;
193219
let storage = extension!(req, Storage);
194220
let config = extension!(req, Config);
195221

@@ -217,8 +243,8 @@ pub fn source_browser_handler(req: &mut Request) -> IronResult<Response> {
217243
(None, false)
218244
};
219245

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)?;
222248

223249
SourcePage {
224250
file_list,
@@ -231,7 +257,7 @@ pub fn source_browser_handler(req: &mut Request) -> IronResult<Response> {
231257

232258
#[cfg(test)]
233259
mod tests {
234-
use crate::test::{assert_success, wrapper};
260+
use crate::test::*;
235261

236262
#[test]
237263
fn cargo_ok_not_skipped() {
@@ -247,4 +273,36 @@ mod tests {
247273
Ok(())
248274
});
249275
}
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+
}
250308
}

0 commit comments

Comments
 (0)