404
Some checks failed
CI / Check typos (push) Successful in 9s
CI / Check links (push) Failing after 11s
CI / Clippy (push) Successful in 1m1s
CI / Build and test (push) Successful in 1m19s
CI / Build container (push) Successful in 1m5s
CI / Deploy on waypoint (push) Successful in 50s
Some checks failed
CI / Check typos (push) Successful in 9s
CI / Check links (push) Failing after 11s
CI / Clippy (push) Successful in 1m1s
CI / Build and test (push) Successful in 1m19s
CI / Build container (push) Successful in 1m5s
CI / Deploy on waypoint (push) Successful in 50s
This commit is contained in:
@@ -52,6 +52,29 @@ pub trait Servable: Send + Sync {
|
||||
) -> Pin<Box<dyn Future<Output = Rendered> + 'a + Send + Sync>>;
|
||||
}
|
||||
|
||||
pub struct Default404 {}
|
||||
impl Servable for Default404 {
|
||||
fn render<'a>(
|
||||
&'a self,
|
||||
_ctx: &'a RequestContext,
|
||||
) -> Pin<Box<dyn Future<Output = Rendered> + 'a + Send + Sync>> {
|
||||
Box::pin(async {
|
||||
return Rendered {
|
||||
code: StatusCode::NOT_FOUND,
|
||||
body: RenderedBody::String("page not found".into()),
|
||||
ttl: Some(TimeDelta::days(30)),
|
||||
immutable: true,
|
||||
headers: HeaderMap::new(),
|
||||
mime: Some(MimeType::Html),
|
||||
};
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// MARK: server
|
||||
//
|
||||
|
||||
pub struct PageServer {
|
||||
/// If true, expired pages will be rerendered before being sent to the user.
|
||||
/// If false, requests never trigger rerenders. We rely on the rerender task.
|
||||
@@ -61,7 +84,9 @@ pub struct PageServer {
|
||||
never_rerender_on_request: bool,
|
||||
|
||||
/// Map of `{ route: page }`
|
||||
pages: Arc<Mutex<HashMap<String, Arc<dyn Servable>>>>,
|
||||
pages: Mutex<HashMap<String, Arc<dyn Servable>>>,
|
||||
|
||||
notfound: Mutex<Arc<dyn Servable>>,
|
||||
|
||||
/// Map of `{ route: (page data, expire time) }`
|
||||
///
|
||||
@@ -75,12 +100,19 @@ impl PageServer {
|
||||
let cache_size = NonZero::new(128).unwrap();
|
||||
|
||||
Arc::new(Self {
|
||||
pages: Arc::new(Mutex::new(HashMap::new())),
|
||||
pages: Mutex::new(HashMap::new()),
|
||||
page_cache: Mutex::new(LruCache::new(cache_size)),
|
||||
never_rerender_on_request: true,
|
||||
notfound: Mutex::new(Arc::new(Default404 {})),
|
||||
})
|
||||
}
|
||||
|
||||
/// Set this server's "not found" page
|
||||
pub fn with_404<S: Servable + 'static>(&self, page: S) -> &Self {
|
||||
*self.notfound.lock() = Arc::new(page);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_page<S: Servable + 'static>(&self, route: impl Into<String>, page: S) -> &Self {
|
||||
#[expect(clippy::expect_used)]
|
||||
let route = route
|
||||
@@ -102,23 +134,23 @@ impl PageServer {
|
||||
reason: &'static str,
|
||||
route: &str,
|
||||
ctx: RequestContext,
|
||||
) -> Option<(Rendered, Option<DateTime<Utc>>)> {
|
||||
) -> (Rendered, Option<DateTime<Utc>>) {
|
||||
let now = Utc::now();
|
||||
let start = Instant::now();
|
||||
|
||||
let page = match self.pages.lock().get(route) {
|
||||
Some(x) => x.clone(),
|
||||
None => return None,
|
||||
None => self.notfound.lock().clone(),
|
||||
};
|
||||
|
||||
trace!(
|
||||
message = "Rendering page",
|
||||
route,
|
||||
route = route.to_owned(),
|
||||
reason,
|
||||
lock_time_ms = start.elapsed().as_millis()
|
||||
);
|
||||
|
||||
let rendered = page.render(&ctx).await;
|
||||
//let html = (self.render_page)(&page, &req_ctx).await.0;
|
||||
|
||||
let mut expires = None;
|
||||
if let Some(ttl) = rendered.ttl {
|
||||
@@ -129,8 +161,13 @@ impl PageServer {
|
||||
}
|
||||
|
||||
let elapsed = start.elapsed().as_millis();
|
||||
trace!(message = "Rendered page", route, reason, time_ms = elapsed);
|
||||
return Some((rendered, expires));
|
||||
trace!(
|
||||
message = "Rendered page",
|
||||
route = route.to_owned(),
|
||||
reason,
|
||||
time_ms = elapsed
|
||||
);
|
||||
return (rendered, expires);
|
||||
}
|
||||
|
||||
async fn handler(
|
||||
@@ -206,30 +243,7 @@ impl PageServer {
|
||||
|
||||
if html_expires.is_none() {
|
||||
cached = false;
|
||||
html_expires = match state.render_page("request", &route, ctx).await {
|
||||
Some(x) => Some(x.clone()),
|
||||
None => {
|
||||
trace!(
|
||||
message = "Not found",
|
||||
route,
|
||||
addr = ?addr.addr,
|
||||
user_agent = ua,
|
||||
device_type = ?client_info.device_type
|
||||
);
|
||||
|
||||
trace!(
|
||||
message = "Served route",
|
||||
route,
|
||||
addr = ?addr.addr,
|
||||
user_agent = ua,
|
||||
device_type = ?client_info.device_type,
|
||||
cached,
|
||||
time_ns = start.elapsed().as_nanos()
|
||||
);
|
||||
|
||||
return StatusCode::NOT_FOUND.into_response();
|
||||
}
|
||||
};
|
||||
html_expires = Some(state.render_page("request", &route, ctx).await);
|
||||
}
|
||||
|
||||
#[expect(clippy::unwrap_used)]
|
||||
|
||||
Reference in New Issue
Block a user