Skip to content

Commit 86d4dad

Browse files
committed
migrate about-pages & metrics to axum
1 parent 83ad0bb commit 86d4dad

File tree

3 files changed

+51
-35
lines changed

3 files changed

+51
-35
lines changed

src/web/metrics.rs

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
use crate::db::Pool;
2-
use crate::BuildQueue;
3-
use crate::Metrics;
1+
use crate::{db::Pool, utils::spawn_blocking, web::error::AxumResult, BuildQueue, Metrics};
2+
use anyhow::Context as _;
43
use axum::{
5-
extract::MatchedPath, http::Request as AxumRequest, middleware::Next, response::IntoResponse,
4+
body::Body,
5+
extract::{Extension, MatchedPath},
6+
http::Request as AxumRequest,
7+
http::{
8+
header::{CONTENT_LENGTH, CONTENT_TYPE},
9+
Response as AxumHttpResponse, StatusCode,
10+
},
11+
middleware::Next,
12+
response::IntoResponse,
613
};
7-
use iron::headers::ContentType;
814
use iron::prelude::*;
9-
use iron::status::Status;
1015
use prometheus::{Encoder, HistogramVec, TextEncoder};
1116
use std::{
1217
borrow::Cow,
@@ -16,20 +21,24 @@ use std::{
1621
#[cfg(test)]
1722
use tracing::debug;
1823

19-
pub(super) fn metrics_handler(req: &mut Request) -> IronResult<Response> {
20-
let metrics = extension!(req, Metrics);
21-
let pool = extension!(req, Pool);
22-
let queue = extension!(req, BuildQueue);
24+
pub(super) async fn metrics_handler(
25+
Extension(pool): Extension<Pool>,
26+
Extension(metrics): Extension<Arc<Metrics>>,
27+
Extension(queue): Extension<Arc<BuildQueue>>,
28+
) -> AxumResult<impl IntoResponse> {
29+
let families = spawn_blocking(move || metrics.gather(&pool, &queue)).await?;
2330

2431
let mut buffer = Vec::new();
25-
let families = ctry!(req, metrics.gather(pool, queue));
26-
ctry!(req, TextEncoder::new().encode(&families, &mut buffer));
32+
TextEncoder::new()
33+
.encode(&families, &mut buffer)
34+
.context("error encoding metrics")?;
2735

28-
let mut resp = Response::with(buffer);
29-
resp.status = Some(Status::Ok);
30-
resp.headers.set(ContentType::plaintext());
31-
32-
Ok(resp)
36+
Ok(AxumHttpResponse::builder()
37+
.status(StatusCode::OK)
38+
.header(CONTENT_TYPE, mime::TEXT_PLAIN.as_ref())
39+
.header(CONTENT_LENGTH, buffer.len())
40+
.body(Body::from(buffer))
41+
.context("error generating response")?)
3342
}
3443

3544
/// Converts a `Duration` to seconds, used by prometheus internally

src/web/routes.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ pub(super) fn build_axum_routes() -> AxumRouter {
6161
"/about/builds",
6262
get_internal(super::sitemap::about_builds_handler),
6363
)
64+
.route(
65+
"/about/metrics",
66+
get_internal(super::metrics::metrics_handler),
67+
)
68+
.route("/about", get_internal(super::sitemap::about_handler))
69+
.route(
70+
"/about/:subpage",
71+
get_internal(super::sitemap::about_handler),
72+
)
6473
.route(
6574
"/releases",
6675
get_internal(super::releases::recent_releases_handler),
@@ -133,10 +142,6 @@ pub(super) fn build_routes() -> Routes {
133142

134143
routes.internal_page("/", super::releases::home_page);
135144

136-
routes.internal_page("/about", super::sitemap::about_handler);
137-
routes.internal_page("/about/metrics", super::metrics::metrics_handler);
138-
routes.internal_page("/about/:subpage", super::sitemap::about_handler);
139-
140145
routes.static_resource("/releases/feed", super::releases::releases_feed_handler);
141146
routes.internal_page("/releases/:owner", super::releases::owner_handler);
142147
routes.internal_page("/releases/:owner/:page", super::releases::owner_handler);

src/web/sitemap.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
use crate::{
22
db::Pool,
33
docbuilder::Limits,
4-
impl_axum_webpage, impl_webpage,
4+
impl_axum_webpage,
55
utils::{get_config, spawn_blocking, ConfigName},
66
web::{
77
error::{AxumNope, AxumResult},
8-
page::WebPage,
8+
AxumErrorPage,
99
},
1010
};
1111
use axum::{
1212
extract::{Extension, Path},
13+
http::StatusCode,
1314
response::IntoResponse,
1415
};
1516
use chrono::{DateTime, TimeZone, Utc};
16-
use iron::{IronResult, Request as IronRequest, Response as IronResponse};
1717
use serde::Serialize;
1818

1919
/// sitemap index
@@ -133,32 +133,34 @@ struct AboutPage<'a> {
133133
active_tab: &'a str,
134134
}
135135

136-
impl_webpage!(AboutPage<'_> = |this: &AboutPage| this.template.clone().into());
136+
impl_axum_webpage!(AboutPage<'_> = |this: &AboutPage| this.template.clone().into());
137137

138-
pub fn about_handler(req: &mut IronRequest) -> IronResult<IronResponse> {
139-
use super::ErrorPage;
140-
use iron::status::Status;
138+
pub(crate) async fn about_handler(subpage: Option<Path<String>>) -> AxumResult<impl IntoResponse> {
139+
let subpage = match subpage {
140+
Some(subpage) => subpage.0,
141+
None => "index".to_string(),
142+
};
141143

142-
let name = match *req.url.path().last().expect("iron is broken") {
144+
let name = match &subpage[..] {
143145
"about" | "index" => "index",
144146
x @ "badges" | x @ "metadata" | x @ "redirections" | x @ "download" => x,
145147
_ => {
146148
let msg = "This /about page does not exist. \
147149
Perhaps you are interested in <a href=\"https://github.com/rust-lang/docs.rs/tree/master/templates/core/about\">creating</a> it?";
148-
let page = ErrorPage {
150+
let page = AxumErrorPage {
149151
title: "The requested page does not exist",
150-
message: Some(msg.into()),
151-
status: Status::NotFound,
152+
message: msg.into(),
153+
status: StatusCode::NOT_FOUND,
152154
};
153-
return page.into_response(req);
155+
return Ok(page.into_response());
154156
}
155157
};
156158
let template = format!("core/about/{}.html", name);
157-
AboutPage {
159+
Ok(AboutPage {
158160
template,
159161
active_tab: name,
160162
}
161-
.into_response(req)
163+
.into_response())
162164
}
163165

164166
#[cfg(test)]

0 commit comments

Comments
 (0)