Skip to content

Commit 29a34c3

Browse files
committed
Actually serve pages without giving a 404
1 parent fa11da3 commit 29a34c3

File tree

9 files changed

+112
-37
lines changed

9 files changed

+112
-37
lines changed

src/web/page/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod templates;
22
mod web_page;
33

44
pub(crate) use templates::TemplateData;
5-
pub(crate) use web_page::WebPage;
5+
pub(super) use web_page::{respond, WebPage};
66

77
use serde::Serialize;
88

src/web/page/web_page.rs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,41 @@ macro_rules! impl_webpage {
2626
};
2727
}
2828

29+
pub(in crate::web) fn respond(
30+
template: &str,
31+
ctx: Context,
32+
content_type: ContentType,
33+
status: Status,
34+
req: &Request,
35+
) -> IronResult<Response> {
36+
let rendered = req
37+
.extensions
38+
.get::<TemplateData>()
39+
.expect("missing TemplateData from the request extensions")
40+
.templates
41+
.load()
42+
.render(template, &ctx)
43+
.unwrap();
44+
45+
let mut response = Response::with((status, rendered));
46+
response.headers.set(content_type);
47+
48+
Ok(response)
49+
}
50+
2951
/// The central trait that rendering pages revolves around, it handles selecting and rendering the template
3052
pub trait WebPage: Serialize + Sized {
3153
/// Turn the current instance into a `Response`, ready to be served
3254
// TODO: We could cache similar pages using the `&Context`
3355
fn into_response(self, req: &Request) -> IronResult<Response> {
3456
let ctx = Context::from_serialize(&self).unwrap();
35-
36-
let rendered = req
37-
.extensions
38-
.get::<TemplateData>()
39-
.expect("missing TemplateData from the request extensions")
40-
.templates
41-
.load()
42-
.render(Self::TEMPLATE, &ctx)
43-
.unwrap();
44-
45-
let mut response = Response::with((self.get_status(), rendered));
46-
response.headers.set(Self::content_type());
47-
48-
Ok(response)
57+
respond(
58+
Self::TEMPLATE,
59+
ctx,
60+
Self::content_type(),
61+
self.get_status(),
62+
req,
63+
)
4964
}
5065

5166
/// The name of the template to be rendered

src/web/routes.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ pub(super) fn build_routes() -> Routes {
2323

2424
routes.internal_page("/about", super::sitemap::about_handler);
2525
routes.internal_page("/about/metrics", super::metrics::metrics_handler);
26+
routes.internal_page("/about/builds", super::sitemap::about_builds_handler);
27+
routes.internal_page("/about/:subpage", super::sitemap::about_handler);
2628

2729
routes.internal_page("/releases", super::releases::recent_releases_handler);
2830
routes.static_resource("/releases/feed", super::releases::releases_feed_handler);

src/web/sitemap.rs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,16 @@ pub fn robots_txt_handler(_: &mut Request) -> IronResult<Response> {
5656
}
5757

5858
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
59-
struct About {
59+
struct AboutBuilds {
6060
/// The current version of rustc that docs.rs is using to build crates
6161
rustc_version: Option<String>,
6262
/// The default crate build limits
6363
limits: Limits,
6464
}
6565

66-
impl_webpage!(About = "core/about/index.html");
66+
impl_webpage!(AboutBuilds = "core/about/builds.html");
6767

68-
pub fn about_handler(req: &mut Request) -> IronResult<Response> {
68+
pub fn about_builds_handler(req: &mut Request) -> IronResult<Response> {
6969
let conn = extension!(req, Pool).get()?;
7070
let res = ctry!(
7171
req,
@@ -80,13 +80,44 @@ pub fn about_handler(req: &mut Request) -> IronResult<Response> {
8080
}
8181
});
8282

83-
About {
83+
AboutBuilds {
8484
rustc_version,
8585
limits: Limits::default(),
8686
}
8787
.into_response(req)
8888
}
8989

90+
pub fn about_handler(req: &mut Request) -> IronResult<Response> {
91+
use super::page::respond;
92+
use super::ErrorPage;
93+
use iron::status::Status;
94+
95+
let template = match *req.url.path().last().expect("iron is broken") {
96+
"about" | "index.html" => "index.html",
97+
"badges" => "badges.html",
98+
"metadata" => "metadata.html",
99+
"redirections" => "redirections.html",
100+
_ => {
101+
let msg = "This /about page does not exist. \
102+
Perhaps you are interested in <a href=\"https://github.com/rust-lang/docs.rs/tree/master/templates/core/about\">creating</a> it?";
103+
let page = ErrorPage {
104+
title: "The requested page does not exist",
105+
message: Some(msg.into()),
106+
status: Status::NotFound,
107+
};
108+
return page.into_response(req);
109+
}
110+
};
111+
let template = format!("core/about/{}", template);
112+
respond(
113+
&template,
114+
tera::Context::new(),
115+
ContentType::html(),
116+
Status::Ok,
117+
req,
118+
)
119+
}
120+
90121
#[cfg(test)]
91122
mod tests {
92123
use crate::test::{assert_success, wrapper};
@@ -110,6 +141,9 @@ mod tests {
110141
fn about_page() {
111142
wrapper(|env| {
112143
let web = env.frontend();
144+
for file in std::fs::read_dir("templates/core/about")? {
145+
assert_success(path?, web)?;
146+
}
113147
assert_success("/about", web)
114148
})
115149
}

templates/core/about/badges.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
<h2>Badges</h2>
1+
{% extends "base.html" -%}
2+
3+
{%- block title -%} Badges {%- endblock title -%}
4+
5+
{%- block body -%}
6+
<h1>Badges</h1>
27

38
<p>
49
You can use badges to show state of your documentation to your users.
@@ -43,3 +48,4 @@ <h2>Badges</h2>
4348
</tr>
4449
</tbody>
4550
</table>
51+
{%- endblock body %}

templates/core/about/builds.html

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
<h2>Builds</h2>
1+
{% extends "base.html" -%}
2+
3+
{%- block title -%} Builds {%- endblock title -%}
4+
5+
{%- block body -%}
6+
{%- set docsrs_repo = "https://github.com/rust-lang/docs.rs" -%}
7+
<h1>Builds</h1>
28
<p>
39
Docs.rs automatically builds crates' documentation released on
410
<a href="https://crates.io/">crates.io</a>
@@ -42,7 +48,7 @@ <h4>Detecting Docs.rs from <code>build.rs</code></h4>
4248
<h4>Detecting Docs.rs from <code>#[cfg]</code> attributes</h4>
4349
<p>
4450
You can detect Docs.rs by having a <a href="https://doc.rust-lang.org/cargo/reference/features.html">feature</a>
45-
which is only set by Docs.rs. See <a href="metadata.html">Metadata</a> for more information.
51+
which is only set by Docs.rs. See <a href="metadata">Metadata</a> for more information.
4652
</p>
4753

4854
<h4>Global sandbox limits</h4>
@@ -68,4 +74,12 @@ <h4>Test crate documentation build locally</h4>
6874
unpublished crate's documentation locally using the same build environment as the build agent.
6975
</p>
7076

71-
<h4></h4>
77+
{%- endblock body %}
78+
79+
{% block css -%}
80+
{{ macros::highlight_css() }}
81+
{%- endblock css %}
82+
83+
{% block javascript -%}
84+
{{ macros::highlight_js(languages=["ini"]) }}
85+
{%- endblock javascript %}

templates/core/about/index.html

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ <h1 id="crate-title">About Docs.rs</h1>
2727

2828
<h2>More about Docs.rs</h2>
2929
<ol>
30-
<li><a href="builds.html">Builds</a>: How Docs.rs builds documentation for a crate</li>
31-
<li><a href="metadata.html">Metadata</a>: How you can configure a build</li>
32-
<li><a href="badges.html">Badges</a>: How to use badges generated by Docs.rs</li>
33-
<li><a href="redirections.html">Redirections</a>: How Docs.rs uses semantic versioning in URLs</li>
30+
<li><a href="/about/builds">Builds</a>: How Docs.rs builds documentation for a crate</li>
31+
<li><a href="/about/metadata">Metadata</a>: How you can configure a build</li>
32+
<li><a href="/about/badges">Badges</a>: How to use badges generated by Docs.rs</li>
33+
<li><a href="/about/redirections">Redirections</a>: How Docs.rs uses semantic versioning in URLs</li>
3434
</ol>
3535

3636
<h3>Version</h3>
@@ -45,11 +45,3 @@ <h3>Contact</h3>
4545

4646
</div>
4747
{%- endblock body %}
48-
49-
{% block css -%}
50-
{{ macros::highlight_css() }}
51-
{%- endblock css %}
52-
53-
{% block javascript -%}
54-
{{ macros::highlight_js(languages=["ini"]) }}
55-
{%- endblock javascript %}

templates/core/about/metadata.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
<h2 id="metadata"><a href="#metadata">Metadata for custom builds</a></h2>
1+
{% extends "base.html" -%}
2+
3+
{%- block title -%} Metadata {%- endblock title -%}
4+
5+
{%- block body -%}
6+
<h1>Metadata for custom builds</h1>
27

38
<p>
49
You can customize docs.rs builds by defining <code>[package.metadata.docs.rs]</code>
@@ -8,3 +13,4 @@ <h2 id="metadata"><a href="#metadata">Metadata for custom builds</a></h2>
813
<p>The available configuration flags you can customize are:</p>
914

1015
<pre><code>{%- include "core/Cargo.toml.example" -%}</code></pre>
16+
{%- endblock body %}

templates/core/about/redirections.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
<h2>Redirections</h2>
1+
{% extends "base.html" -%}
2+
3+
{%- block title -%} Redirections {%- endblock title -%}
4+
5+
{%- block body -%}
6+
<h1>Redirections</h1>
27

38
<p>
49
Docs.rs uses semver to parse URLs. You can use this feature to access
@@ -50,3 +55,4 @@ <h2>Redirections</h2>
5055
</tr>
5156
</tbody>
5257
</table>
58+
{%- endblock body %}

0 commit comments

Comments
 (0)