poem-web / poem

A full-featured and easy-to-use web framework with the Rust programming language.
Apache License 2.0
3.6k stars 293 forks source link

Transform errors when extract parameters #814

Open tisonkun opened 5 months ago

tisonkun commented 5 months ago

Description of the feature

This code snippet:

#[handler]
async fn query(
    Json(query): Json<Query>,
) -> String {
    query.query
}

would be expanded to:

#[allow(non_camel_case_types)]
struct query;
impl poem::Endpoint for query {
    type Output = poem::Response;
    #[allow(unused_mut)]
    async fn call(&self, mut req: poem::Request) -> poem::Result<Self::Output> {
        let (req, mut body) = req.split();
        let p0 = <Json<Query> as poem::FromRequest>::from_request(&req, &mut body)
            .await?;
        async fn query(Json(query): Json<Query>) -> String {
            query.query
        }
        let res = query(p0).await;
        let res = poem::error::IntoResult::into_result(res);
        std::result::Result::map(res, poem::IntoResponse::into_response)
    }
}

I know I can change the return type of my function to customize error in my handling logic, but what if I'd like to decorate the error message when fail to <Json<Query> as poem::FromRequest>::from_request(&req, &mut body).await??.

Code example (if possible)

By default, it may return:

HTTP/1.1 400 Bad Request
Content-Length: 77
Connection: keep-alive
Date: Sun, 12 May 2024 06:30:37 GMT
Keep-Alive: timeout=4
Proxy-Connection: keep-alive

parse error: invalid type: integer `1`, expected a string at line 1 column 12

while I'd prefer to customize the error message, like:

HTTP/1.1 400 Bad Request
Content-Length: 77
Connection: keep-alive
Date: Sun, 12 May 2024 06:30:37 GMT
Keep-Alive: timeout=4
Proxy-Connection: keep-alive

0: fail to parse JSON payoad, at src/lib.rs:4:10
1: parse error: invalid type: integer `1`, expected a string at line 1 column 12
tisonkun commented 5 months ago

By default, the extractor will return a 400 Bad Request when an error occurs, but sometimes you may want to change this behavior, so you can handle the error yourself.

In the following example, when the Query extractor fails, it will return a 500 Internal Server response and the reason for the error.

Seems like we can use a Result<[Extractor]> extractor?