seanmonstar/warp

Return the appropriate error message.

Opened this issue · 0 comments

Version
web_warp v0.1.0 (/home/ubuntu/learn/rust/web_warp)
└── warp v0.3.5

Platform
Linux ubuntu 5.4.0-126-generic #142-Ubuntu SMP Fri Aug 26 12:12:57 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Description
In the scenario where both request parameters and custom request methods are present, if the request parameters are incorrect while the request method is correct, the returned error will still be from the custom request method.

[short summary of the bug]
Bug summary: When both request parameters and custom request methods are present, if the request parameters are incorrect while the request method is correct, the error returned is still from the custom request method instead of indicating a parameter error.
I tried this code:

use std::net::SocketAddr;
use std::time::Duration;
use tokio::time;
use warp::{hyper::Method, reject, Filter, Rejection};

#[derive(Debug)]
struct MethodError;
impl reject::Reject for MethodError {}

const FOO_METHOD: &'static str = "FOO";

fn method(name: &'static str) -> impl Filter<Extract = (), Error = Rejection> + Clone {
    warp::method()
        .and_then(move |m: Method| async move {
            if m == name {
                Ok(())
            } else {
                Err(warp::reject::custom(MethodError))
            }
        })
        .untuple_one()
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let address: SocketAddr = "[::]:3030".parse()?;

    let root = warp::path("custom").and(warp::path::end());

    let foo_route = root
        .and(method(FOO_METHOD))
        .and(warp::body::json())
        .and_then(move |cp: ChangePassword| async move {
            println!("{:?}", cp);
            time::sleep(Duration::from_secs(3)).await;
            if true {
                Ok("123".to_string())
            }else {
                Err(warp::reject::custom(MethodError))
            }
        });

    let bar_route = root
        .and(warp::post())
        .and(warp::body::json())
        .and_then(move |cu: CreateUser| async move {
            println!("{:?}", cu);
            time::sleep(Duration::from_secs(1)).await;
            if true {
                Ok("456".to_string())
            }else {
                Err(warp::reject())
            }
        });

    warp::serve(bar_route.or(foo_route))
        .run(address)
        .await;

    Ok(())
}

use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize)]
pub struct ChangePassword {
    pub password_1: String,
    pub password_2: String
}

#[derive(Deserialize, Debug, Serialize)]
pub struct CreateUser {
    pub username: String,
    pub email: String
}

[curl command]
curl -X POST http://127.0.0.1:3030/custom

[Current Response]
Unhandled rejection: MethodError

I expected to see this happen: [explanation]
Request body deserialize error: EOF while parsing a value at line 1 column 0