diff options
Diffstat (limited to 'kittybox-rs/src/main.rs')
-rw-r--r-- | kittybox-rs/src/main.rs | 129 |
1 files changed, 68 insertions, 61 deletions
diff --git a/kittybox-rs/src/main.rs b/kittybox-rs/src/main.rs index 50c0ca5..59c3e69 100644 --- a/kittybox-rs/src/main.rs +++ b/kittybox-rs/src/main.rs @@ -110,11 +110,55 @@ async fn main() { kittybox::media::storage::file::FileStore::new(path) }; - let svc = axum::Router::new() + // This code proves that different components of Kittybox can + // be split up without hurting the app + // + // If needed, some features could be omitted from the binary + // or just not spun up in the future + // + // For example, the frontend code could run spearately from + // Micropub and only have read access to the database folder + let frontend = axum::Router::new() .route( "/", - axum::routing::get(kittybox::frontend::homepage::<FileStorage>), - ) + axum::routing::get(kittybox::frontend::homepage::<FileStorage>) + .layer(axum::Extension(database.clone()))) + .route("/.kittybox/static/:path", axum::routing::get(kittybox::frontend::statics)) + .fallback( + axum::routing::get(kittybox::frontend::catchall::<FileStorage>) + .layer(axum::Extension(database.clone()))); + + // Onboarding is a bit of a special case. One might argue that + // the onboarding makes Kittybox a monolith. This is wrong. + // The "onboarding receiver" doesn't need any code from the + // onboarding form - they're grouped in a single module for + // convenience only, since modifying one usually requires + // updating the other to match. + // + // For example, this "router" just groups two separate methods + // in one request, because logically they live in the same + // subtree. But one could manually construct only one but not + // the other, to receive a "frontend-only" application. Of + // course, in this scenario, one must employ a reverse proxy + // to distinguish between GET and POST requests to the same + // path, and route them to the correct set of endpoints with + // write access. + let onboarding = axum::Router::new() + .route("/.kittybox/onboarding", kittybox::frontend::onboarding::router( + database.clone(), http.clone() + )); + + let micropub = axum::Router::new() + .route("/.kittybox/micropub", kittybox::micropub::router(database.clone(), http.clone())) + .nest("/.kittybox/micropub/client", kittybox::companion::router()); + + let media = axum::Router::new() + .nest("/.kittybox/media", kittybox::media::router(blobstore).layer(axum::Extension(http))); + + /*let indieauth = axum::Router::new() + .nest("/.kittybox/indieauth", kittybox::indieauth::router());*/ + + let technical = axum::Router::new() .route( "/.kittybox/coffee", axum::routing::get(|| async { @@ -127,71 +171,34 @@ async fn main() { }), ) .route( - "/.kittybox/onboarding", - axum::routing::get(kittybox::frontend::onboarding::get) - .post(kittybox::frontend::onboarding::post::<FileStorage>), - ) - .route( - "/.kittybox/micropub", - axum::routing::get(kittybox::micropub::query::<FileStorage>) - .post(kittybox::micropub::post::<FileStorage>) - .layer( - tower_http::cors::CorsLayer::new() - .allow_methods([axum::http::Method::GET, axum::http::Method::POST]) - .allow_origin(tower_http::cors::Any), - ), - ) - .route( - "/.kittybox/micropub/client", - axum::routing::get(|| { - std::future::ready(axum::response::Html(kittybox::MICROPUB_CLIENT)) - }), - ) - .route( "/.kittybox/health", - axum::routing::get(|| async { + axum::routing::get( + |axum::Extension(db): axum::Extension<FileStorage>| async move { // TODO health-check the database "OK" - }), + } + ) + .layer(axum::Extension(database)) ) .route( "/.kittybox/metrics", axum::routing::get(|| async { todo!() }), - ) - .nest( - "/.kittybox/media", - axum::Router::new() - .route( - "/", - axum::routing::get(|| async { todo!() }) - .post( - kittybox::media::upload::<kittybox::media::FileStore> - ), - ) - .route("/uploads/*file", axum::routing::get( - kittybox::media::serve::<kittybox::media::FileStore> - )), - ) - .route( - "/.kittybox/static/:path", - axum::routing::get(kittybox::frontend::statics), - ) - .fallback(axum::routing::get( - kittybox::frontend::catchall::<FileStorage>, - )) - .layer(axum::Extension(database)) - .layer(axum::Extension(http)) - .layer(axum::Extension(kittybox::tokenauth::TokenEndpoint( - token_endpoint, - ))) - .layer(axum::Extension(blobstore)) - .layer( - tower::ServiceBuilder::new() - .layer(tower_http::trace::TraceLayer::new_for_http()) - .into_inner(), ); - // A little dance to turn a potential file descriptor into a guaranteed async network socket + let svc = axum::Router::new() + .merge(frontend) + .merge(onboarding) + .merge(micropub) + .merge(media) + //.merge(indieauth) + .merge(technical) + .layer(axum::Extension(kittybox::tokenauth::TokenEndpoint(token_endpoint))) + .layer(tower::ServiceBuilder::new() + .layer(tower_http::trace::TraceLayer::new_for_http()) + .into_inner()); + + // A little dance to turn a potential file descriptor into + // a guaranteed async network socket let tcp_listener: std::net::TcpListener = { let mut listenfd = listenfd::ListenFd::from_env(); @@ -200,8 +207,8 @@ async fn main() { } else { std::net::TcpListener::bind(listen_at).unwrap() }; - // Set the socket to non-blocking so tokio can work with it properly - // This is the async magic + // Set the socket to non-blocking so tokio can poll it + // properly -- this is the async magic! tcp_listener.set_nonblocking(true).unwrap(); tcp_listener |