carllerche / tower-web

A fast, boilerplate free, web framework for Rust
MIT License
980 stars 51 forks source link

Allow to set custom status code and error details for extract::error::Error #216

Open manifest opened 5 years ago

manifest commented 5 years ago

Missing value don't always assume "404 Bad Request" status code. For instance in case of authorization it would be more appropriate to return "403 Forbidden" if access token is required by the application. At the same time, some applications may want to process requests from anonymous users along with authorized ones.

impl_web! {
    impl Resource {
        #[get("/foo")]
        fn foo(&self, t: Token) -> Result<String, ()> {
            Ok(String::from("user"))
        }

        fn bar(&self, t: Option<Token>) -> Result<String, ()> {
            match t {
                Some(_) => Ok(String::from("user")),
                None => Ok(String::from("anonymous")),
            }
        }
    }
}

Currently, that is impossible to specify status code or any additional details of the extract::error::Error

struct Token;

impl<B: BufStream> Extract<B> for Token {
    type Future = Immediate<Token>;

    fn extract(context: &Context) -> Self::Future {
        match context.request().headers().get(http::header::AUTHORIZATION) {
            Some(_) => Immediate::ok(Token{}),
            None => Immediate::err(Error::missing_argument()),
        }
    }
}

The proposal is to change the extract::error::Error to make such error customization possible:

impl<B: BufStream> Extract<B> for Token {
    type Future = Immediate<Token>;

    fn extract(context: &Context) -> Self::Future {
        match context.request().headers().get(http::header::AUTHORIZATION) {
            Some(_) => Immediate::ok(Token{}),
            None => Immediate::err(Error::missing(forbidden())),
        }
    }
}

fn forbidden() -> tower_web::Error {
    tower_web::Error::from(StatusCode::FORBIDDEN)
}
lnicola commented 5 years ago

Fixed in #217.