Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Examples (or design?) around error handling #116

Closed
petejodo opened this issue Jan 15, 2019 · 4 comments
Closed

Examples (or design?) around error handling #116

petejodo opened this issue Jan 15, 2019 · 4 comments

Comments

@petejodo
Copy link
Collaborator

There are no examples about error handling, nor does it look like there has been any discussion around error handling in general. Created this issue for fleshing this out.

I tried writing a handler with the return type Result<Json<User>, MyError> but I was running into compiler errors. I don't have the time right now to post the example but will when I get the time

@petejodo
Copy link
Collaborator Author

so I actually got it to work, it was a simple mistake of missing a ?. That's what I get for trying to get it working so early in the morning. Anyway I made a super basic example:

#![feature(async_await, futures_api)]

use serde_derive::Serialize;

#[derive(Serialize)]
struct MyError {
    error: String,
}

impl tide::IntoResponse for MyError {
    fn into_response(self) -> tide::Response {
        http::Response::builder()
            .status(http::status::StatusCode::INTERNAL_SERVER_ERROR)
            .header("Content-Type", "application/json")
            .body(tide::body::Body::from(serde_json::to_vec(&self).unwrap()))
            .unwrap()
    }
}

#[derive(Serialize)]
struct MyData {
    name: String,
}

async fn my_handler(param: tide::head::Path<usize>) -> Result<tide::body::Json<MyData>, MyError> {
    if param.0 > 0 {
        Ok(tide::body::Json(MyData {
            name: "John".to_string(),
        }))
    } else {
        Err(MyError {
            error: "Value was less than or equal to 0".to_string(),
        })
    }
}

fn main() {
    let mut app = tide::App::new(());
    app.at("/test/{}").get(my_handler);

    let address = "127.0.0.1:8000".to_owned();
    println!("Server is listening on http://{}", address);
    app.serve(address);
}

Some issues with this currently is having to build my own response for my error since tide::body::Json is only for successful responses. This means accessing http itself. Speaking of which, a panic occurs at request time Attempted to yield error response with success code 200 when implementing IntoResponse for MyError via tide::body::Json(self).into_response(). Not sure if it's possible, but it'd be cool if this was somehow caught at least at start up time.

In actual usage, a user will want to be converting from a lot of different potential errors e.g. database query errors, etc, etc which then need to be translated to specific status codes so coming up with a streamlined way to do this would be useful. Maybe this means using something like error_chain or failure? Idk. I'm still very amateurish at Rust so I don't know the advantage of either or even if they're necessary for this use case.

Another type of error handling that's separate from this, is deserialization errors. Currently tide just responds with a 400 Bad Request which is similar to what Rocket does and Rocket does not provide any way to handle that either. Not sure what a user would want to actually show for those cases but the ability to handle it should still probably be there

@tirr-c
Copy link
Collaborator

tirr-c commented Jan 15, 2019

It would be nice if we had a wrapper that takes IntoResponse type and modify status code, add extra headers etc.

@petejodo
Copy link
Collaborator Author

I pulled in the most recent changes and have been messing around with it to see what kind of example I could come up with. I created this gist of where I'm currently at. I have two types HandlerError and ErrorResponse. HandlerError is the individual errors and ErrorResponse is the normalized struct that responds as a json. ErrorResponse is what tide endpoints would use as the result error type e.g.

async fn hello_world() -> Result<T, ErrorResponse> {
    // ...
}

there's still more work to do around it though

@petejodo
Copy link
Collaborator Author

petejodo commented Mar 7, 2019

#138 is structured more like a formal issue surrounding error handling. Closing this in favor of that issue.

@petejodo petejodo closed this as completed Mar 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants