Skip to content

Commit 0e5bda9

Browse files
committed
add caching to crate-features endpoint
1 parent 2cd5531 commit 0e5bda9

File tree

1 file changed

+57
-12
lines changed

1 file changed

+57
-12
lines changed

src/web/features.rs

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::db::types::Feature;
33
use crate::{
44
db::Pool,
55
impl_webpage,
6-
web::{page::WebPage, MetaData},
6+
web::{cache::CachePolicy, page::WebPage, MetaData},
77
};
88
use iron::{IronResult, Request, Response, Url};
99
use router::Router;
@@ -30,10 +30,10 @@ pub fn build_features_handler(req: &mut Request) -> IronResult<Response> {
3030
let req_version = router.find("version");
3131

3232
let mut conn = extension!(req, Pool).get()?;
33-
let (version, version_or_latest) =
33+
let (version, version_or_latest, is_latest_url) =
3434
match match_version(&mut conn, name, req_version).and_then(|m| m.assume_exact())? {
35-
MatchSemver::Exact((version, _)) => (version.clone(), version),
36-
MatchSemver::Latest((version, _)) => (version, "latest".to_string()),
35+
MatchSemver::Exact((version, _)) => (version.clone(), version, false),
36+
MatchSemver::Latest((version, _)) => (version, "latest".to_string(), true),
3737

3838
MatchSemver::Semver((version, _)) => {
3939
let url = ctry!(
@@ -46,7 +46,7 @@ pub fn build_features_handler(req: &mut Request) -> IronResult<Response> {
4646
)),
4747
);
4848

49-
return Ok(super::redirect(url));
49+
return Ok(super::cached_redirect(url, CachePolicy::ForeverInCdn));
5050
}
5151
};
5252
let rows = ctry!(
@@ -70,7 +70,7 @@ pub fn build_features_handler(req: &mut Request) -> IronResult<Response> {
7070
default_len = result.1;
7171
}
7272

73-
FeaturesPage {
73+
let mut response = FeaturesPage {
7474
metadata: cexpect!(
7575
req,
7676
MetaData::from_crate(&mut conn, name, &version, &version_or_latest)
@@ -79,7 +79,13 @@ pub fn build_features_handler(req: &mut Request) -> IronResult<Response> {
7979
default_len,
8080
canonical_url: format!("https://docs.rs/crate/{}/latest/features", name),
8181
}
82-
.into_response(req)
82+
.into_response(req)?;
83+
response.extensions.insert::<CachePolicy>(if is_latest_url {
84+
CachePolicy::ForeverInCdn
85+
} else {
86+
CachePolicy::ForeverInCdnAndStaleInBrowser
87+
});
88+
Ok(response)
8389
}
8490

8591
fn order_features_and_count_default_len(raw: Vec<Feature>) -> (Vec<Feature>, usize) {
@@ -121,12 +127,9 @@ fn get_feature_map(raw: Vec<Feature>) -> HashMap<String, Feature> {
121127

122128
#[cfg(test)]
123129
mod tests {
130+
use super::*;
124131
use crate::db::types::Feature;
125-
use crate::test::wrapper;
126-
use crate::web::features::{
127-
get_feature_map, get_tree_structure_from_default, order_features_and_count_default_len,
128-
DEFAULT_NAME,
129-
};
132+
use crate::test::{assert_cache_control, assert_redirect_cached, wrapper};
130133
use reqwest::StatusCode;
131134
use std::collections::HashMap;
132135

@@ -246,6 +249,46 @@ mod tests {
246249
assert_eq!(features[1], non_default);
247250
}
248251

252+
#[test]
253+
fn semver_redirect() {
254+
wrapper(|env| {
255+
env.fake_release()
256+
.name("foo")
257+
.version("0.2.1")
258+
.features(HashMap::new())
259+
.create()?;
260+
261+
assert_redirect_cached(
262+
"/crate/foo/~0.2/features",
263+
"/crate/foo/0.2.1/features",
264+
CachePolicy::ForeverInCdn,
265+
env.frontend(),
266+
&env.config(),
267+
)?;
268+
Ok(())
269+
});
270+
}
271+
272+
#[test]
273+
fn specific_version_correctly_cached() {
274+
wrapper(|env| {
275+
env.fake_release()
276+
.name("foo")
277+
.version("0.2.0")
278+
.features(HashMap::new())
279+
.create()?;
280+
281+
let resp = env.frontend().get("/crate/foo/0.2.0/features").send()?;
282+
assert!(resp.status().is_success());
283+
assert_cache_control(
284+
&resp,
285+
CachePolicy::ForeverInCdnAndStaleInBrowser,
286+
&env.config(),
287+
);
288+
Ok(())
289+
});
290+
}
291+
249292
#[test]
250293
fn latest_200() {
251294
wrapper(|env| {
@@ -262,6 +305,8 @@ mod tests {
262305
.create()?;
263306

264307
let resp = env.frontend().get("/crate/foo/latest/features").send()?;
308+
assert!(resp.status().is_success());
309+
assert_cache_control(&resp, CachePolicy::ForeverInCdn, &env.config());
265310
assert!(resp.url().as_str().ends_with("/crate/foo/latest/features"));
266311
let body = String::from_utf8(resp.bytes().unwrap().to_vec()).unwrap();
267312
assert!(body.contains("<a href=\"/crate/foo/latest/builds\""));

0 commit comments

Comments
 (0)