summaryrefslogtreecommitdiff
path: root/src/cli.rs
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2025-06-17 00:46:24 -0400
committerOwen Jacobson <owen@grimoire.ca>2025-06-17 01:08:19 -0400
commit424fb08ecd315c67dd3862c29e87eea7bf32f65c (patch)
treebf85cba9c93766b8651d16de9984bbeb48d58fdf /src/cli.rs
parent4a7fb2c5cf7265c5ef6a78051c1bb73e7d3ef086 (diff)
Unify `setup_required` middlewares.
The two middlewares were identical but for the specific `IntoResponse` impl used to generate the response when setup has not been completed. However, unifying them while still using `from_fn_with_state` lead to this horrorshow: .route_layer(middleware::from_fn_with_state( app.clone(), |state, req, next| { setup::middeware::setup_required(UNAVAILABLE, state, req, next) } )) It's a lot to read, and it surfaces the entire signature of a state-driven middleware `fn` into the call site solely to close over one argument (`UNAVAILABLE`). Rather than doing that, I've converted this middleware into a full blown Tower middleware, following <https://docs.rs/axum/latest/axum/middleware/index.html#towerservice-and-pinboxdyn-future>. I considered taking this further and implementing a custom future to remove the allocation for `Box::pin`, but honestly, that allocation isn't hurting anyone and this code already got long enough in the translation. The new API looks like: .route_layer(setup::Required::or_unavailable(app.clone())) Or like: .route_layer(setup::Required::with_fallback(app.clone(), RESPONSE)) One thing I would have liked to have avoided is the additional `app.clone()` argument, but there isn't a way to extract the _state_ from a request inside of an Axum middleware. It has to be passed in externally - that's what `from_fn_with_state` is doing under the hood, as well. Using `State` as an extractor doesn't work; the `State` extractor is special in a _bunch_ of ways, and this is one of them. Other extractors would work. Realistically, I'd probably want to explore interfaces like .route_layer(setup::Required(app).or_unavailable()) or .route_layer(app.setup().required().or_unavailable())
Diffstat (limited to 'src/cli.rs')
-rw-r--r--src/cli.rs9
1 files changed, 2 insertions, 7 deletions
diff --git a/src/cli.rs b/src/cli.rs
index 4232c00..042141d 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -15,12 +15,7 @@ use clap::{CommandFactory, Parser};
use sqlx::sqlite::SqlitePool;
use tokio::net;
-use crate::{
- app::App,
- boot, channel, clock, db, event, expire, invite, message,
- setup::{self, middleware::setup_required},
- ui, user,
-};
+use crate::{app::App, boot, channel, clock, db, event, expire, invite, message, setup, ui, user};
/// Command-line entry point for running the `pilcrow` server.
///
@@ -152,7 +147,7 @@ fn routers(app: &App) -> Router<App> {
app.clone(),
expire::middleware,
))
- .route_layer(middleware::from_fn_with_state(app.clone(), setup_required)),
+ .route_layer(setup::Required::or_unavailable(app.clone())),
// API endpoints that handle setup
setup::router(),
// The UI (handles setup state itself)