Skip to content

Commit

Permalink
Redirect to a 404 page when serving translated
Browse files Browse the repository at this point in the history
We can't redirect in warp based on the URL, so redirect to the default
language's 404 page instead.

See: seanmonstar/warp#171
  • Loading branch information
Ruin0x11 committed Sep 15, 2021
1 parent 85ab4d3 commit 282fdaa
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 69 deletions.
34 changes: 21 additions & 13 deletions src/book/book.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,37 @@ pub fn load_book<P: AsRef<Path>>(
if cfg.language.has_localized_dir_structure() {
match build_opts.language_ident {
// Build a single book's translation.
Some(_) => Ok(LoadedBook::Single(load_single_book_translation(&root_dir, cfg, &build_opts.language_ident)?)),
Some(_) => Ok(LoadedBook::Single(load_single_book_translation(
&root_dir,
cfg,
&build_opts.language_ident,
)?)),
// Build all available translations at once.
None => {
let mut translations = HashMap::new();
for (lang_ident, _) in cfg.language.0.iter() {
let book = load_single_book_translation(&root_dir, cfg, &Some(lang_ident.clone()))?;
let book =
load_single_book_translation(&root_dir, cfg, &Some(lang_ident.clone()))?;
translations.insert(lang_ident.clone(), book);
}
Ok(LoadedBook::Localized(LocalizedBooks(translations)))
}
}
} else {
Ok(LoadedBook::Single(load_single_book_translation(&root_dir, cfg, &None)?))
Ok(LoadedBook::Single(load_single_book_translation(
&root_dir, cfg, &None,
)?))
}
}

fn load_single_book_translation<P: AsRef<Path>>(root_dir: P, cfg: &Config, language_ident: &Option<String>) -> Result<Book> {
let localized_src_dir = root_dir.as_ref().join(
cfg.get_localized_src_path(language_ident.as_ref())
.unwrap(),
);
fn load_single_book_translation<P: AsRef<Path>>(
root_dir: P,
cfg: &Config,
language_ident: &Option<String>,
) -> Result<Book> {
let localized_src_dir = root_dir
.as_ref()
.join(cfg.get_localized_src_path(language_ident.as_ref()).unwrap());
let fallback_src_dir = root_dir.as_ref().join(cfg.get_fallback_src_path());

let summary_md = localized_src_dir.join("SUMMARY.md");
Expand Down Expand Up @@ -172,9 +182,7 @@ impl LocalizedBooks {
items.extend(book.iter().items);
}

BookItems {
items: items
}
BookItems { items: items }
}

/// Recursively apply a closure to each item in the book, allowing you to
Expand Down Expand Up @@ -239,7 +247,7 @@ impl LoadedBook {
pub fn first(&self) -> &Book {
match self {
LoadedBook::Localized(books) => books.0.iter().next().unwrap().1,
LoadedBook::Single(book) => &book
LoadedBook::Single(book) => &book,
}
}
}
Expand Down Expand Up @@ -617,7 +625,7 @@ more text.
Vec::new(),
&cfg,
)
.unwrap();
.unwrap();
assert_eq!(got, should_be);
}

Expand Down
21 changes: 14 additions & 7 deletions src/book/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ mod book;
mod init;
mod summary;

pub use self::book::{load_book, BookItem, BookItems, Chapter, Book, LocalizedBooks, LoadedBook};
pub use self::book::{load_book, Book, BookItem, BookItems, Chapter, LoadedBook, LocalizedBooks};
pub use self::init::BookBuilder;
pub use self::summary::{parse_summary, Link, SectionNumber, Summary, SummaryItem};

use std::collections::HashMap;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;
use std::string::ToString;
use std::collections::HashMap;
use tempfile::Builder as TempFileBuilder;
use tempfile::TempDir;
use toml::Value;
Expand Down Expand Up @@ -133,8 +133,12 @@ impl MDBook {
.unwrap(),
);
let fallback_src_dir = root.join(config.get_fallback_src_path());
let book =
LoadedBook::Single(book::load_book_from_disk(&summary, localized_src_dir, fallback_src_dir, &config)?);
let book = LoadedBook::Single(book::load_book_from_disk(
&summary,
localized_src_dir,
fallback_src_dir,
&config,
)?);

let renderers = determine_renderers(&config);
let preprocessors = determine_preprocessors(&config)?;
Expand Down Expand Up @@ -223,13 +227,16 @@ impl MDBook {
let mut new_books = HashMap::new();

for (ident, book) in books.0.iter() {
let preprocessed_book = self.preprocess(&preprocess_ctx, renderer, book.clone())?;
let preprocessed_book =
self.preprocess(&preprocess_ctx, renderer, book.clone())?;
new_books.insert(ident.clone(), preprocessed_book);
}

LoadedBook::Localized(LocalizedBooks(new_books))
},
LoadedBook::Single(ref book) => LoadedBook::Single(self.preprocess(&preprocess_ctx, renderer, book.clone())?),
}
LoadedBook::Single(ref book) => {
LoadedBook::Single(self.preprocess(&preprocess_ctx, renderer, book.clone())?)
}
};

let name = renderer.name();
Expand Down
35 changes: 25 additions & 10 deletions src/cmd/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
Some(lang_ident) => Some(lang_ident.clone()),
// If not, it will be at the root.
None => None,
}
},
};

let sockaddr: SocketAddr = address
Expand Down Expand Up @@ -177,9 +177,6 @@ async fn serve(
});
// A warp Filter that serves from the filesystem.
let book_route = warp::fs::dir(build_dir.clone());
// The fallback route for 404 errors
let fallback_route = warp::fs::file(build_dir.join(file_404))
.map(|reply| warp::reply::with_status(reply, warp::http::StatusCode::NOT_FOUND));

std::panic::set_hook(Box::new(move |panic_info| {
// exit if serve panics
Expand All @@ -189,13 +186,31 @@ async fn serve(

if let Some(lang_ident) = language {
// Redirect root to the default translation directory, if serving a localized book.
// BUG: This can't be `/{lang_ident}`, or the static assets won't get loaded.
let index_for_language = format!("/{}/index.html", lang_ident).parse::<Uri>().unwrap();
let redirect_to_index = warp::path::end().map(move || warp::redirect(index_for_language.clone()));
let routes = livereload.or(redirect_to_index).or(book_route).or(fallback_route);
// NOTE: This can't be `/{lang_ident}`, or the static assets won't get loaded.
// BUG: Redirects get cached if you change the --language parameter,
// meaning you'll get a 404 unless you disable cache in the developer tools.
let index_for_language = format!("/{}/index.html", lang_ident)
.parse::<Uri>()
.unwrap();
let redirect_to_index =
warp::path::end().map(move || warp::redirect(index_for_language.clone()));

// BUG: It is not possible to conditionally redirect to the correct 404
// page depending on the URL in warp, so just redirect to the one in the
// default language.
// See: https://github.com/seanmonstar/warp/issues/171
let fallback_route = warp::fs::file(build_dir.join(lang_ident).join(file_404))
.map(|reply| warp::reply::with_status(reply, warp::http::StatusCode::NOT_FOUND));

let routes = livereload
.or(redirect_to_index)
.or(book_route)
.or(fallback_route);
warp::serve(routes).run(address).await;
}
else {
} else {
// The fallback route for 404 errors
let fallback_route = warp::fs::file(build_dir.join(file_404))
.map(|reply| warp::reply::with_status(reply, warp::http::StatusCode::NOT_FOUND));
let routes = livereload.or(book_route).or(fallback_route);
warp::serve(routes).run(address).await;
};
Expand Down
3 changes: 2 additions & 1 deletion src/preprocess/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ mod tests {
);

let mut buffer = Vec::new();
cmd.write_input(&mut buffer, &md.book.first(), &ctx).unwrap();
cmd.write_input(&mut buffer, &md.book.first(), &ctx)
.unwrap();

let (got_ctx, got_book) = CmdPreprocessor::parse_input(buffer.as_slice()).unwrap();

Expand Down
80 changes: 57 additions & 23 deletions src/renderer/html_handlebars/hbs_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,31 +62,49 @@ impl HtmlHandlebars {
let mut path = src_dir.clone();
path.push(lang_ident);
path
},
}
// `src_dir` is where index.html and the other extra files
// are, so use that.
None => src_dir.clone()
None => src_dir.clone(),
};
self.render_book(ctx, &book, src_dir, &extra_file_dir, &ctx.destination, &ctx.config.build.build_dir, html_config, handlebars, theme)?;
self.render_book(
ctx,
&book,
src_dir,
&extra_file_dir,
&ctx.destination,
&ctx.config.build.build_dir,
html_config,
handlebars,
theme,
)?;
}
}

Ok(())
}

fn render_book<'a>(&self,
ctx: &RenderContext,
book: &Book,
src_dir: &PathBuf,
extra_file_dir: &PathBuf,
destination: &PathBuf,
build_dir: &PathBuf,
html_config: &HtmlConfig,
handlebars: &mut Handlebars<'a>,
theme: &Theme,
fn render_book<'a>(
&self,
ctx: &RenderContext,
book: &Book,
src_dir: &PathBuf,
extra_file_dir: &PathBuf,
destination: &PathBuf,
build_dir: &PathBuf,
html_config: &HtmlConfig,
handlebars: &mut Handlebars<'a>,
theme: &Theme,
) -> Result<()> {
let build_dir = ctx.root.join(build_dir);
let mut data = make_data(&ctx.root, &book, &ctx.book, &ctx.config, &html_config, &theme)?;
let mut data = make_data(
&ctx.root,
&book,
&ctx.book,
&ctx.config,
&html_config,
&theme,
)?;

// Print version
let mut print_content = String::new();
Expand All @@ -110,7 +128,14 @@ impl HtmlHandlebars {

// Render 404 page
if html_config.input_404 != Some("".to_string()) {
self.render_404(ctx, &html_config, src_dir, destination, handlebars, &mut data)?;
self.render_404(
ctx,
&html_config,
src_dir,
destination,
handlebars,
&mut data,
)?;
}

// Print version
Expand All @@ -123,7 +148,8 @@ impl HtmlHandlebars {
debug!("Render template");
let rendered = handlebars.render("index", &data)?;

let rendered = self.post_process(rendered, &html_config.playground, ctx.config.rust.edition);
let rendered =
self.post_process(rendered, &html_config.playground, ctx.config.rust.edition);

utils::fs::write_file(&destination, "print.html", rendered.as_bytes())?;
debug!("Creating print.html ✓");
Expand All @@ -147,12 +173,17 @@ impl HtmlHandlebars {
.context("Unable to emit redirects")?;

// Copy all remaining files, avoid a recursive copy from/to the book build dir
utils::fs::copy_files_except_ext(&extra_file_dir, &destination, true, Some(&build_dir), &["md"])?;
utils::fs::copy_files_except_ext(
&extra_file_dir,
&destination,
true,
Some(&build_dir),
&["md"],
)?;

Ok(())
}


fn render_item(
&self,
item: &BookItem,
Expand Down Expand Up @@ -229,7 +260,7 @@ impl HtmlHandlebars {
);
if let Some(ref section) = ch.number {
ctx.data
.insert("section".to_owned(), json!(section.to_string()));
.insert("section".to_owned(), json!(section.to_string()));
}

// Render the handlebars template with the data
Expand Down Expand Up @@ -461,7 +492,10 @@ impl HtmlHandlebars {
handlebars.register_helper("previous", Box::new(helpers::navigation::previous));
handlebars.register_helper("next", Box::new(helpers::navigation::next));
handlebars.register_helper("theme_option", Box::new(helpers::theme::theme_option));
handlebars.register_helper("language_option", Box::new(helpers::language::language_option));
handlebars.register_helper(
"language_option",
Box::new(helpers::language::language_option),
);
}

/// Copy across any additional CSS and JavaScript files which the book
Expand Down Expand Up @@ -568,7 +602,7 @@ impl HtmlHandlebars {
fn maybe_wrong_theme_dir(dir: &Path) -> Result<bool> {
fn entry_is_maybe_book_file(entry: fs::DirEntry) -> Result<bool> {
Ok(entry.file_type()?.is_file()
&& entry.path().extension().map_or(false, |ext| ext == "md"))
&& entry.path().extension().map_or(false, |ext| ext == "md"))
}

if dir.is_dir() {
Expand Down Expand Up @@ -842,7 +876,7 @@ fn make_data(
languages.sort();
data.insert("languages".to_owned(), json!(languages));
data.insert("language_config".to_owned(), json!(config.language.clone()));
},
}
LoadedBook::Single(_) => {
data.insert("languages_enabled".to_owned(), json!(false));
}
Expand Down Expand Up @@ -1012,7 +1046,7 @@ fn add_playground_pre(
"\n# #![allow(unused)]\n{}#fn main() {{\n{}#}}",
attrs, code
)
.into()
.into()
};
hide_lines(&content)
}
Expand Down

0 comments on commit 282fdaa

Please sign in to comment.