I have 3 filters, if I combine them in order a,c,b, the code compiles. But if I switch their orders like a,b,c, the code won't compile. The filter seems the same to me. Why?
use reqwest::Method;
use serde_json::Value;
use warp::http::{HeaderMap, StatusCode};
use warp::path::FullPath;
use warp::reply::Response;
use std::convert::Infallible;
use warp::{Filter, Reply};
async fn fn_with_params_no_body(method: Method, path: FullPath, headers: HeaderMap, query: String) -> Result<Response, Infallible> {
Ok(StatusCode::OK.into_response())
}
async fn fn_no_params_no_body(method: Method, path: FullPath, headers: HeaderMap) -> Result<Response, Infallible> {
Ok(StatusCode::OK.into_response())
}
async fn fn_no_params_with_body(method: Method, path: FullPath, headers: HeaderMap, body: Value) -> Result<Response, Infallible> {
Ok(StatusCode::OK.into_response())
}
#[tokio::main]
async fn main() {
let ep0 = warp::any()
.and(warp::method())
.and(warp::path::full())
.and(warp::header::headers_cloned())
.and(warp::query::raw())
.and_then(fn_with_params_no_body);
let ep1 = warp::any()
.and(warp::method())
.and(warp::path::full())
.and(warp::header::headers_cloned())
.and_then(fn_no_params_no_body);
let ep2 = warp::any()
.and(warp::method())
.and(warp::path::full())
.and(warp::header::headers_cloned())
.and(warp::body::json())
.and_then(fn_no_params_with_body);
let routes = ep0.or(ep2).or(ep1); // this would compile
// let routes = ep0.or(ep1).or(ep2); // this won't
warp::serve(routes)
.run(([0, 0, 0, 0], 8080))
.await
}
It says expected struct Rejection, found enum Infallible and or requires Self: Filter<Error = Rejection> + Sized, then why can I compile it after swithcing orders, none of the handle functions returns Result<Response, Reject>
--> exproxy/src/main.rs:43:30
|
43 | let routes = ep0.or(ep1).or(ep2);
|
|
note: required by a bound in `or`
--> /Users/ynx/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.3.2/src/filter/mod.rs:140:22
|
140 | Self: Filter<Error = Rejection> + Sized,
| ^^^^^^^^^^^^^^^^^ required by this bound in `or`
The error message says it all. When
ep1is called, it ends withfn_with_params_no_bodyso it returns eitherInfalliableorResponse. In the order that works, first theep0is checked, and if the route has parameters, it succeeds and doesn't keep going down theorchain. This means that the numbers after it will be sure that the route has no parameters. Whenep2is reached, it can be sure that the input will have no routes, so it only bothers to check for the body. If it has a body, then it will succeed and stop the chain. Only if it's certain that the route has no route or body,ep1is run. Since it's the last one, and it's already known that there is no body or route (or else the previous functions would have worked)ep1is guaranteed to return aInfalliable. Any other order runs the risk of not returning anInfalliable, or as your error happened, passing a value that is alreadyInfalilliableto one of the filters