Skip to content

Commit 894a5d4

Browse files
Nemo157Joshua Nelson
authored and
Joshua Nelson
committed
Refactor static file handling to only use a single handler
* Moved the static files out of templates/ and src/ (both as static files that got included in the build, and as static strings in the source) into the static/ directory * Copied the static/ directory into the docker image as static/ * Removed the `staticfile` handler serving from $CRATESFYI_PREFIX/public_html/ since those files are now in static/
1 parent 8f42dff commit 894a5d4

File tree

14 files changed

+90
-99
lines changed

14 files changed

+90
-99
lines changed

build.rs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
use git2::Repository;
2-
use std::{
3-
env,
4-
error::Error,
5-
fs::{self, File},
6-
io::Write,
7-
path::Path,
8-
};
2+
use std::{env, error::Error, fs::File, io::Write, path::Path};
93

104
fn main() {
115
// Don't rerun anytime a single change is made
@@ -15,8 +9,6 @@ fn main() {
159
println!("cargo:rerun-if-changed=templates/style/_vars.scss");
1610
println!("cargo:rerun-if-changed=templates/style/_utils.scss");
1711
println!("cargo:rerun-if-changed=templates/style/_navbar.scss");
18-
println!("cargo:rerun-if-changed=templates/menu.js");
19-
println!("cargo:rerun-if-changed=templates/index.js");
2012
println!("cargo:rerun-if-changed=vendor/");
2113
// TODO: are these right?
2214
println!("cargo:rerun-if-changed=.git/HEAD");
@@ -26,7 +18,6 @@ fn main() {
2618
if let Err(sass_err) = compile_sass() {
2719
panic!("Error compiling sass: {}", sass_err);
2820
}
29-
copy_js();
3021
}
3122

3223
fn write_git_version() {
@@ -95,12 +86,3 @@ fn compile_sass() -> Result<(), Box<dyn Error>> {
9586

9687
Ok(())
9788
}
98-
99-
fn copy_js() {
100-
["menu.js", "index.js"].iter().for_each(|path| {
101-
let source_path =
102-
Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join(format!("templates/{}", path));
103-
let dest_path = Path::new(&env::var("OUT_DIR").unwrap()).join(path);
104-
fs::copy(&source_path, &dest_path).expect("Copy JavaScript file to target");
105-
});
106-
}

dockerfiles/Dockerfile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ RUN touch build.rs
5151
COPY src src/
5252
RUN find src -name "*.rs" -exec touch {} \;
5353
COPY templates/style templates/style
54-
COPY templates/index.js templates/
55-
COPY templates/menu.js templates/
5654
COPY vendor vendor/
5755

5856
RUN cargo build --release
@@ -76,7 +74,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
7674
RUN mkdir -p /opt/docsrs/prefix
7775

7876
COPY --from=build /build/target/release/cratesfyi /usr/local/bin
79-
COPY static /opt/docsrs/prefix/public_html
77+
COPY static /opt/docsrs/static
8078
COPY templates /opt/docsrs/templates
8179
COPY dockerfiles/entrypoint.sh /opt/docsrs/
8280
COPY vendor /opt/docsrs/vendor

src/web/error.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ mod tests {
144144
.next()
145145
.unwrap()
146146
.text_contents(),
147-
"The requested resource does not exist",
147+
"The requested crate does not exist",
148148
);
149149

150150
Ok(())
@@ -170,7 +170,7 @@ mod tests {
170170
.next()
171171
.unwrap()
172172
.text_contents(),
173-
"The requested resource does not exist",
173+
"The requested crate does not exist",
174174
);
175175

176176
Ok(())
@@ -190,7 +190,7 @@ mod tests {
190190
.next()
191191
.unwrap()
192192
.text_contents(),
193-
"The requested resource does not exist",
193+
"The requested crate does not exist",
194194
);
195195

196196
Ok(())
@@ -209,7 +209,7 @@ mod tests {
209209
.next()
210210
.unwrap()
211211
.text_contents(),
212-
"The requested resource does not exist",
212+
"The requested crate does not exist",
213213
);
214214

215215
Ok(())
@@ -232,7 +232,7 @@ mod tests {
232232
.next()
233233
.unwrap()
234234
.text_contents(),
235-
"The requested resource does not exist",
235+
"The requested crate does not exist",
236236
);
237237

238238
Ok(())

src/web/metrics.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ mod tests {
119119
("/crate/rcc/0.0.0", "/crate/:name/:version"),
120120
("/-/static/index.js", "static resource"),
121121
("/-/static/menu.js", "static resource"),
122-
("/opensearch.xml", "static resource"),
122+
("/-/static/opensearch.xml", "static resource"),
123123
("/releases", "/releases"),
124124
("/releases/feed", "static resource"),
125125
("/releases/queue", "/releases/queue"),
@@ -129,8 +129,8 @@ mod tests {
129129
"/releases/recent-failures/:page",
130130
),
131131
("/releases/recent/1", "/releases/recent/:page"),
132-
("/robots.txt", "static resource"),
133-
("/sitemap.xml", "static resource"),
132+
("/-/static/robots.txt", "static resource"),
133+
("/-/sitemap.xml", "static resource"),
134134
("/-/static/style.css", "static resource"),
135135
("/-/static/vendored.css", "static resource"),
136136
];

src/web/mod.rs

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ use extensions::InjectExtensions;
9797
use failure::Error;
9898
use iron::{
9999
self,
100-
headers::{CacheControl, CacheDirective, ContentType, Expires, HttpDate},
100+
headers::{Expires, HttpDate},
101101
modifiers::Redirect,
102102
status,
103103
status::Status,
@@ -108,20 +108,17 @@ use postgres::Client;
108108
use router::NoRoute;
109109
use semver::{Version, VersionReq};
110110
use serde::Serialize;
111-
use staticfile::Static;
112-
use std::{borrow::Cow, env, fmt, net::SocketAddr, path::PathBuf, sync::Arc, time::Duration};
111+
use std::{borrow::Cow, fmt, net::SocketAddr, sync::Arc};
113112

114113
/// Duration of static files for staticfile and DatabaseFileHandler (in seconds)
115114
const STATIC_FILE_CACHE_DURATION: u64 = 60 * 60 * 24 * 30 * 12; // 12 months
116-
const OPENSEARCH_XML: &[u8] = include_bytes!("opensearch.xml");
117115

118116
const DEFAULT_BIND: &str = "0.0.0.0:3000";
119117

120118
struct CratesfyiHandler {
121119
shared_resource_handler: Box<dyn Handler>,
122120
router_handler: Box<dyn Handler>,
123121
database_file_handler: Box<dyn Handler>,
124-
static_handler: Box<dyn Handler>,
125122
inject_extensions: InjectExtensions,
126123
}
127124

@@ -145,13 +142,6 @@ impl CratesfyiHandler {
145142
let shared_resources =
146143
Self::chain(inject_extensions.clone(), rustdoc::SharedResourceHandler);
147144
let router_chain = Self::chain(inject_extensions.clone(), routes.iron_router());
148-
let prefix = PathBuf::from(
149-
env::var("CRATESFYI_PREFIX")
150-
.expect("the CRATESFYI_PREFIX environment variable is not set"),
151-
)
152-
.join("public_html");
153-
let static_handler =
154-
Static::new(prefix).cache(Duration::from_secs(STATIC_FILE_CACHE_DURATION));
155145

156146
Ok(CratesfyiHandler {
157147
shared_resource_handler: Box::new(shared_resources),
@@ -160,7 +150,6 @@ impl CratesfyiHandler {
160150
blacklisted_prefixes,
161151
Box::new(file::DatabaseFileHandler),
162152
)),
163-
static_handler: Box::new(static_handler),
164153
inject_extensions,
165154
})
166155
}
@@ -186,7 +175,6 @@ impl Handler for CratesfyiHandler {
186175
.handle(req)
187176
.or_else(|e| if_404(e, || self.router_handler.handle(req)))
188177
.or_else(|e| if_404(e, || self.database_file_handler.handle(req)))
189-
.or_else(|e| if_404(e, || self.static_handler.handle(req)))
190178
.or_else(|e| {
191179
let err = if let Some(err) = e.error.downcast::<error::Nope>() {
192180
*err
@@ -519,21 +507,6 @@ fn redirect_base(req: &Request) -> String {
519507
}
520508
}
521509

522-
fn opensearch_xml_handler(_: &mut Request) -> IronResult<Response> {
523-
let mut response = Response::with((status::Ok, OPENSEARCH_XML));
524-
let cache = vec![
525-
CacheDirective::Public,
526-
CacheDirective::MaxAge(STATIC_FILE_CACHE_DURATION as u32),
527-
];
528-
response.headers.set(ContentType(
529-
"application/opensearchdescription+xml".parse().unwrap(),
530-
));
531-
532-
response.headers.set(CacheControl(cache));
533-
534-
Ok(response)
535-
}
536-
537510
/// MetaData used in header
538511
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
539512
pub(crate) struct MetaData {

src/web/routes.rs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,18 @@ pub(super) const DOC_RUST_LANG_ORG_REDIRECTS: &[&str] =
1010
pub(super) fn build_routes() -> Routes {
1111
let mut routes = Routes::new();
1212

13-
routes.static_resource("/robots.txt", super::sitemap::robots_txt_handler);
14-
routes.static_resource("/sitemap.xml", super::sitemap::sitemap_handler);
15-
routes.static_resource("/opensearch.xml", super::opensearch_xml_handler);
13+
routes.static_resource("/robots.txt", PermanentRedirect("/-/static/robots.txt"));
14+
routes.static_resource("/favicon.ico", PermanentRedirect("/-/static/favicon.ico"));
15+
16+
// These should not need to be served from the root as we reference the inner path in links,
17+
// but clients might have cached the url and need to update it.
18+
routes.static_resource(
19+
"/opensearch.xml",
20+
PermanentRedirect("/-/static/opensearch.xml"),
21+
);
22+
routes.static_resource("/sitemap.xml", PermanentRedirect("/-/sitemap.xml"));
23+
24+
routes.static_resource("/-/sitemap.xml", super::sitemap::sitemap_handler);
1625
routes.static_resource("/-/static/:file", super::statics::static_handler);
1726

1827
routes.internal_page("/", super::releases::home_page);
@@ -257,7 +266,21 @@ impl Handler for SimpleRedirect {
257266
(self.url_mangler)(&mut url);
258267
Ok(iron::Response::with((
259268
iron::status::Found,
260-
iron::modifiers::Redirect(iron::Url::parse(&url.to_string()).unwrap()),
269+
iron::modifiers::Redirect(iron::Url::from_generic_url(url).unwrap()),
270+
)))
271+
}
272+
}
273+
274+
#[derive(Copy, Clone)]
275+
struct PermanentRedirect(&'static str);
276+
277+
impl Handler for PermanentRedirect {
278+
fn handle(&self, req: &mut iron::Request) -> iron::IronResult<iron::Response> {
279+
let mut url: iron::url::Url = req.url.clone().into();
280+
url.set_path(self.0);
281+
Ok(iron::Response::with((
282+
iron::status::MovedPermanently,
283+
iron::modifiers::Redirect(iron::Url::from_generic_url(url).unwrap()),
261284
)))
262285
}
263286
}
@@ -299,3 +322,29 @@ fn calculate_id(pattern: &str) -> String {
299322
.map(|c| if c.is_alphanumeric() { c } else { '_' })
300323
.collect()
301324
}
325+
326+
#[cfg(test)]
327+
mod tests {
328+
use crate::test::*;
329+
330+
#[test]
331+
fn test_root_redirects() {
332+
wrapper(|env| {
333+
// These are "well-known" resources that must be served from the root
334+
assert_redirect("/favicon.ico", "/-/static/favicon.ico", env.frontend())?;
335+
assert_redirect("/robots.txt", "/-/static/robots.txt", env.frontend())?;
336+
337+
// These have previously been served with a url pointing to the root, it may be
338+
// plausible to remove the redirects in the future, but for now we need to keep serving
339+
// them.
340+
assert_redirect(
341+
"/opensearch.xml",
342+
"/-/static/opensearch.xml",
343+
env.frontend(),
344+
)?;
345+
assert_redirect("/sitemap.xml", "/-/sitemap.xml", env.frontend())?;
346+
347+
Ok(())
348+
});
349+
}
350+
}

src/web/sitemap.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use chrono::{DateTime, NaiveDateTime, Utc};
33
use iron::{
44
headers::ContentType,
55
mime::{Mime, SubLevel, TopLevel},
6-
status, IronResult, Request, Response,
6+
IronResult, Request, Response,
77
};
88
use serde::Serialize;
99
use serde_json::Value;
@@ -48,13 +48,6 @@ pub fn sitemap_handler(req: &mut Request) -> IronResult<Response> {
4848
SitemapXml { releases }.into_response(req)
4949
}
5050

51-
pub fn robots_txt_handler(_: &mut Request) -> IronResult<Response> {
52-
let mut resp = Response::with((status::Ok, "Sitemap: https://docs.rs/sitemap.xml"));
53-
resp.headers.set(ContentType::plaintext());
54-
55-
Ok(resp)
56-
}
57-
5851
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
5952
struct AboutBuilds {
6053
/// The current version of rustc that docs.rs is using to build crates

0 commit comments

Comments
 (0)