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

How is the Error type of FromRequest used? #1145

Closed
sclasen opened this issue Sep 28, 2019 · 13 comments
Closed

How is the Error type of FromRequest used? #1145

sclasen opened this issue Sep 28, 2019 · 13 comments
Labels
question A question (converts to discussion)

Comments

@sclasen
Copy link

sclasen commented Sep 28, 2019

I have implemented a custom guard, that returns a Failure with a Status and Json<MyError> when the guard fails. I was expecting that the response returned by rocket would be content type application/json and that the body would be the json serialization of MyError.

Instead, the Status returned from the guard does appear to be used, but the response body are all the default html error responses from rocket.

Is there a way to convince rocket to render the Error type of the Outcome as the body of the error response?

impl FromRequest<'_, '_> for SomeGuardType {
    type Error = Json<MyError>;

    fn from_request(request: &Request) -> Outcome<SomeGuardType, Json<MyError>> {
...
     }
}

Questions

Any questions must include:

  1. The version of Rocket this question is based on, if any.

0.4.2

  1. What steps you've taken to answer the question yourself.

Reading docs, searching for examples, etc.

  1. What documentation you believe should include an answer to this question.

FromRequest api docs, Custom Guard guide.

@sclasen
Copy link
Author

sclasen commented Sep 28, 2019

https://github.com/SergioBenitez/Rocket/blob/master/core/lib/src/request/from_request.rs#L86-L88

seems to indicate that the error type does get used in some way, but I m not able to make the leap to how a catcher would be able to extract/get the Error

@jebrosen jebrosen added the question A question (converts to discussion) label Sep 28, 2019
@jebrosen
Copy link
Collaborator

This looks a lot like #749, but for FromRequest instead of in a fairing.

You can access the error itself in a route by taking result: Result<SomeGuardType, Json<MyError>>, but you cannot access it in a catcher.

@sclasen
Copy link
Author

sclasen commented Sep 28, 2019

thanks @jebrosen is there a canonical way/any way to respond to Err results/Failure outcomes where if the type inside the Err/Failure itself is a Responder, it is used to generate the response body? stash it in request local state and pull it out in custom catchers for the status codes in question? Somehow encode it better in a type, and implement a Responder for that type?

If I take that result described above, there isnt any way to access the Status returned in the Failure from the RequestGuard is there?

Seem like you have to choose between Status and Error when using a request guard, using a Result<GuardType, ErrorType> in your route signature lets you have the error but not the status, and using GuardType lets your Failure status propagate to the matching catcher without the ability to get the ErrorType

@sclasen
Copy link
Author

sclasen commented Sep 28, 2019

looks like the request local state stashing + custom catcher things works out.

@jebrosen
Copy link
Collaborator

is there a canonical way/any way to respond to Err results/Failure outcomes where if the type inside the Err/Failure itself is a Responder, it is used to generate the response body?

We actually do want to support that somehow, but it's effectively blocked on a rust language feature.

Seem like you have to choose between Status and Error when using a request guard

In a sense yes: The Error type is visible only when using Result<RequestGuard, RequestGuard::Error> and the Status is visible only by it determining which catcher is used.

In the future it might be nice to support things like

#[catch(400)]
fn my_errors(error: ErrorType) -> Json<ErrorType> {
    Json(error)
}

But that would require some design and is basically blocked on non_static_type_id the last time we tried.

@sclasen
Copy link
Author

sclasen commented Sep 29, 2019

Thanks, was able to get to a decent place by passing the request guard errors through request.local_cache and having custom catchers, and also a custom responder that wraps the Result responder.

@WilliamVenner
Copy link

WilliamVenner commented Jun 15, 2021

Couldn't a custom status be useful here?

I quite expected rocket::request::Outcome::Failure to be able to accept a rocket::response::status::Custom. It would be great if I can create a custom status code and set its reason myself, which can then be accessed in a catcher.

@SergioBenitez
Copy link
Member

Couldn't a custom status be useful here?

I quite expected rocket::request::Outcome::Failure to be able to accept a rocket::response::status::Custom. It would be great if I can create a custom status code and set its reason myself, which can then be accessed in a catcher.

The failure outcome already does contain a Status.

@SergioBenitez
Copy link
Member

Couldn't a custom status be useful here?

I quite expected rocket::request::Outcome::Failure to be able to accept a rocket::response::status::Custom. It would be great if I can create a custom status code and set its reason myself, which can then be accessed in a catcher.

The failure outcome already does contain a Status. You can access the status in a catcher. The reason phrase cannot be set as this would be non-standard and doesn't offer much utility (and also impossible with the underlying HTTP library.)

@WilliamVenner
Copy link

Yes, it does already contain a Status. It would be good if it can accept rocket::response::status::Custom.

@SergioBenitez
Copy link
Member

SergioBenitez commented Jun 15, 2021

A Custom<T> is a (Status, T). This is exactly what the Failure variant of a FromRequest is.

@thomaseizinger
Copy link

Is there a way of telling rocket to at least log the error in case a request guard emits Outcome::Failure?
I am using rocket with a custom tracing setup (i.e. dedicated EnvFilter and FmtSubscriber) and there is no log output of the error returned by a request guard.

@ananyo141
Copy link

ananyo141 commented Jan 7, 2024

Thanks, was able to get to a decent place by passing the request guard errors through request.local_cache and having custom catchers, and also a custom responder that wraps the Result responder.

Hello there @sclasen , it looks like you were able to solve this issue by using request local cache. However I am stuck here, a beginner in rocket and rust in general, would be really helpful if I can get a hint about the implementation. Read the docs at https://rocket.rs/v0.5/guide/state/#request-local-state and https://api.rocket.rs/v0.5/rocket/request/trait.FromRequest.html#request-local-state but stuck while catching the error in catchers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question A question (converts to discussion)
Projects
None yet
Development

No branches or pull requests

6 participants