How do I use Router::or
with TraceLayer
?
#335
-
Hello! I'm trying to use
But I get this weird error:
Thought I followed the documentation pretty closely, but I'm not able to get past this. Works if I remove the TraceLayer. Works if I use either api_router or health_router separately. Would appreciate any help! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
The issue here is that So the two routers don't have the same response body type meaning they cannot be combined. The solution is to call Here is a full example: use axum::{
handler::get,
Router,
};
use std::net::SocketAddr;
use tower_http::trace::TraceLayer;
#[tokio::main]
async fn main() {
let api_router = Router::new()
.route("/graphql", get(|| async {}))
.layer(TraceLayer::new_for_http())
.boxed();
let health_router = Router::new().route("/health", get(|| async {}));
let app = api_router.or(health_router);
// run it
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
tracing::debug!("listening on {}", addr);
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
} |
Beta Was this translation helpful? Give feedback.
The issue here is that
Trace
(applied byTraceLayer
) changes the response body type. By default axum's response body type isaxum::body::BoxBody
butTrace
changes that totower_http::trace::ResponseBody
. It does this because it needs to know when the body as been fully sent. You can see that in itsService
implementation.So the two routers don't have the same response body type meaning they cannot be combined. The solution is to call
.boxed()
on the one with theTraceLayer
so.layer(TraceLayer::new_for_http()).boxed()
. That changes the response body type so they now both match.Here is a full example: