Skip to content

Commit e8d4c31

Browse files
Serve shared rustdoc resources via special handler
This removes the need for things like onur/rust@482575f and allows launching a local docs.rs instance without having to build a patched compiler.
1 parent 416a2c0 commit e8d4c31

File tree

2 files changed

+38
-3
lines changed

2 files changed

+38
-3
lines changed

src/web/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const OPENSEARCH_XML: &'static [u8] = include_bytes!("opensearch.xml");
6969

7070

7171
struct CratesfyiHandler {
72+
shared_resource_handler: Box<Handler>,
7273
router_handler: Box<Handler>,
7374
database_file_handler: Box<Handler>,
7475
static_handler: Box<Handler>,
@@ -186,12 +187,14 @@ impl CratesfyiHandler {
186187
rustdoc::rustdoc_html_server_handler,
187188
"crate_version_target_html");
188189

190+
let shared_resources = Self::chain(rustdoc::SharedResourceHandler);
189191
let router_chain = Self::chain(router);
190192
let prefix = PathBuf::from(env::var("CRATESFYI_PREFIX").unwrap()).join("public_html");
191193
let static_handler = Static::new(prefix)
192194
.cache(Duration::from_secs(STATIC_FILE_CACHE_DURATION));
193195

194196
CratesfyiHandler {
197+
shared_resource_handler: Box::new(shared_resources),
195198
router_handler: Box::new(router_chain),
196199
database_file_handler: Box::new(file::DatabaseFileHandler),
197200
static_handler: Box::new(static_handler),
@@ -202,10 +205,13 @@ impl CratesfyiHandler {
202205

203206
impl Handler for CratesfyiHandler {
204207
fn handle(&self, req: &mut Request) -> IronResult<Response> {
205-
// try router first then db/static file handler
208+
// try serving shared rustdoc resources first, then router, then db/static file handler
206209
// return 404 if none of them return Ok
207-
self.router_handler
210+
self.shared_resource_handler
208211
.handle(req)
212+
.or_else(|e| {
213+
self.router_handler.handle(req).or(Err(e))
214+
})
209215
.or_else(|e| {
210216
// if router fails try to serve files from database first
211217
self.database_file_handler.handle(req).or(Err(e))

src/web/rustdoc.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_serialize::json::{Json, ToJson};
1616
use std::collections::BTreeMap;
1717
use iron::headers::{Expires, HttpDate, CacheControl, CacheDirective};
1818
use time;
19-
19+
use iron::Handler;
2020

2121

2222
#[derive(Debug)]
@@ -110,6 +110,10 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
110110
}
111111

112112

113+
/// Serves documentation generated by rustdoc.
114+
///
115+
/// This includes all HTML files for an individual crate, as well as the `search-index.js`, which is
116+
/// also crate-specific.
113117
pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult<Response> {
114118

115119
let router = extension!(req, Router);
@@ -251,3 +255,28 @@ pub fn badge_handler(req: &mut Request) -> IronResult<Response> {
251255
CacheDirective::MustRevalidate]));
252256
Ok(resp)
253257
}
258+
259+
/// Serves shared web resources used by rustdoc-generated documentation.
260+
///
261+
/// This includes common `css` and `js` files that only change when the compiler is updated, but are
262+
/// otherwise the same for all crates documented with that compiler. Those have a custom handler to
263+
/// deduplicate them and save space.
264+
pub struct SharedResourceHandler;
265+
266+
impl Handler for SharedResourceHandler {
267+
fn handle(&self, req: &mut Request) -> IronResult<Response> {
268+
let path = req.url.path();
269+
let filename = path.last().unwrap(); // unwrap is fine: vector is non-empty
270+
let suffix = filename.split('.').last().unwrap(); // unwrap is fine: split always works
271+
if ["js", "css", "woff", "svg"].contains(&suffix) {
272+
let conn = extension!(req, Pool);
273+
274+
if let Some(file) = File::from_path(conn, filename) {
275+
return Ok(file.serve());
276+
}
277+
}
278+
279+
// Just always return a 404 here - the main handler will then try the other handlers
280+
Err(IronError::new(Nope::ResourceNotFound, status::NotFound))
281+
}
282+
}

0 commit comments

Comments
 (0)