leotaku / tower-livereload

Tower middleware to automatically reload your web browser during development
Apache License 2.0
59 stars 5 forks source link

axum: layer is ignored with router's `fallback` #9

Closed lbonn closed 5 months ago

lbonn commented 6 months ago

When adding a 404 fallback route, routes internal to livereload (long-poll, back-up) are eaten up and return 404 as well.

Probably axum only expects middlewares to act on existing routes and not define their own? In that case, not sure how to fix this... Maybe expose the route handlers so that they can be called in explicit routes defined by the user?

Reproduction: apply this patch to the axum-dev-only example

diff --git a/examples/axum-dev-only/src/main.rs b/examples/axum-dev-only/src/main.rs
index e0c415a..c62cd7b 100644
--- a/examples/axum-dev-only/src/main.rs
+++ b/examples/axum-dev-only/src/main.rs
@@ -1,11 +1,11 @@
-use axum::{response::Html, routing::get, Router};
+use axum::{http::StatusCode, response::Html, routing::get, Router};

 #[tokio::main]
 async fn main() -> Result<(), Box<dyn std::error::Error>> {
     let app = Router::new().route("/", get(|| async { Html("<h1>Wow, such webdev</h1>") }));

     #[cfg(debug_assertions)]
-    let app = app.layer(tower_livereload::LiveReloadLayer::new());
+    let app = app.layer(tower_livereload::LiveReloadLayer::new()).fallback(|| async { StatusCode::NOT_FOUND });

     let listener = tokio::net::TcpListener::bind("0.0.0.0:3030").await?;
     axum::serve(listener, app).await?;
leotaku commented 5 months ago

Hi and sorry for the delayed reply!

As far as I understand and the documentation describes, layers are only added to routes that already exists, which also applies to fallback routes. As such you should be able to reorder your method calls from .layer(...).fallback(...) to .fallback(...).layer(...) and achieve your desired behaviour.

lbonn commented 5 months ago

Ah I've missed this bit indeed, makes sense now :)

Thanks a lot!