Cannot work with tower-http's RequestDecompressionLayer
Closed this issue · 3 comments
tisonkun commented
Bug Report
Version
│ │ │ │ │ │ │ ├── axum v0.6.20
│ │ │ │ │ │ │ │ ├── axum-core v0.3.4
│ │ │ │ │ │ │ │ ├── axum v0.6.20 (*)
│ │ │ │ │ │ │ │ │ │ │ ├── axum v0.6.20
│ │ │ │ │ │ │ │ │ │ │ │ ├── axum-core v0.3.4 (*)
│ │ │ │ │ │ │ │ │ │ ├── axum v0.6.20 (*)
│ │ │ │ │ │ │ │ │ │ ├── axum-macros v0.3.8 (proc-macro)
│ │ │ │ │ │ │ │ │ │ ├── axum-test-helper v0.3.0
│ │ │ │ │ │ │ │ │ │ │ ├── axum v0.6.20 (*)
├── axum v0.6.20 (*)
├── axum-test-helper v0.3.0 (*)
Platform
Darwin tisondeMacBook-Pro.local 22.5.0 Darwin Kernel Version 22.5.0: Mon Apr 24 20:53:19 PDT 2023; root:xnu-8796.121.2~5/RELEASE_ARM64_T6020 arm64
Crates
Description
Router::new()
.route("/write", routing::post(influxdb_write_v1))
.route("/api/v2/write", routing::post(influxdb_write_v2))
.layer(RequestDecompressionLayer::new())
.route("/ping", routing::get(influxdb_ping))
.route("/health", routing::get(influxdb_health))
.with_state(influxdb_handler)
throws
Compiling servers v0.7.0 (/Users/tison/GreptimeWorkspace/greptimedb/src/servers)
error[E0277]: the trait bound `Infallible: std::convert::From<Box<(dyn StdError + std::marker::Send + std::marker::Sync + 'static)>>` is not satisfied
--> src/servers/src/http.rs:702:20
|
702 | .layer(RequestDecompressionLayer::new().gzip(true))
| ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<Box<(dyn StdError + std::marker::Send + std::marker::Sync + 'static)>>` is not implemented for `Infallible`
| |
| required by a bound introduced by this call
|
= help: the trait `std::convert::From<!>` is implemented for `Infallible`
= help: for that trait implementation, expected `!`, found `Box<(dyn StdError + std::marker::Send + std::marker::Sync + 'static)>`
= note: required for `Box<(dyn StdError + std::marker::Send + std::marker::Sync + 'static)>` to implement `Into<Infallible>`
note: required by a bound in `AxumRouter::<S, B>::layer`
--> /Users/tison/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.6.20/src/routing/mod.rs:238:62
|
233 | pub fn layer<L, NewReqBody>(self, layer: L) -> Router<S, NewReqBody>
| ----- required by a bound in this associated function
...
238 | <L::Service as Service<Request<NewReqBody>>>::Error: Into<Infallible> + 'static,
| ^^^^^^^^^^^^^^^^ required by this bound in `Router::<S, B>::layer`
For more information about this error, try `rustc --explain E0277`.
tisonkun commented
But the TimeoutLayer in tower has the same:
impl<S> Layer<S> for TimeoutLayer {
type Service = Timeout<S>;
fn layer(&self, service: S) -> Self::Service {
Timeout::new(service, self.timeout)
}
}
impl<S, Request> Service<Request> for Timeout<S>
where
S: Service<Request>,
S::Error: Into<crate::BoxError>,
{
type Response = S::Response;
type Error = crate::BoxError;
type Future = ResponseFuture<S::Future>;
....
}
pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
why this one gets compiled?
tisonkun commented
Work around with:
.layer(
ServiceBuilder::new()
.layer(HandleErrorLayer::new(handle_error))
.layer(RequestDecompressionLayer::new()),
)
where
async fn handle_error(err: BoxError) -> Json<HttpResponse> {
error!(err; "Unhandled internal error");
Json(HttpResponse::Error(...))
}
jplatte commented
HandleErrorLayer
is the correct solution. See the documentation for more details.
With regards to TimeoutLayer
, I suspect you are mixing up tower
's TimeoutLayer
which does raise service-level errors, with tower-http
s TimeoutLayer
which doesn't.
Next time if you have a problem like this and it's not clear whether it's a bug in axum, please use the Q&A section. Thanks!