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::BoxBodybutTracechanges 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 itsServiceimplementation.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 theTraceLayerso.layer(TraceLayer::new_for_http()).boxed(). That changes the response body type so they now both match.Here is a full example: