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
Allow custom validation response #30
Allow custom validation response #30
Conversation
Thank you for your contribution! Within the next few days I'm afraid I won't have time to look into this PR but I will try to find some time later on. |
Sorry it took so long, I have a few personal things going on. So this PR looks really well. You're right it'd be better if 4xx was returned instead. I have a few comments though. Do you want me to accept it as is and change a few things or do you want to discuss comments? |
Thank you for the review. I agree there should be some changes as per your comments, I'll experiment with a callback-based implementation. |
with a deeper look, the mentioned rate-limiting middleware ends up doing the same weird double |
42d6f57
to
f83b977
Compare
f83b977
to
00b6a06
Compare
Thanks. It looks very good now. I'll give it another look over the weekend. |
Ehh... I was thinking about one thing and wrote something else. Of course, it's not user-friendly. A huge part of my review was not entirely correct, especially the callback/base exception thing. Now I gave it a thought and I think there's only one correct way of handling those. To my knowledge, all web frameworks have a central place where they handle errors. Starlette is a framework so it imposes a certain way of handling them as well, in the ExceptionMiddleware. If you had middleware A, B , C and RawContextMiddleware, create a response in RawContextMiddleware, the rest of them will process the response as if it was a success response. So for instance ASGISentryMiddleware etc. wouldn't catch the error. It's just asking for trouble. We need to do things Starlette-way.
class InvalidUUIDError(HTTPException):
def __init__(self, status_code: int = status.HTTP_422_UNPROCESSABLE_ENTITY, detail: str = 'Invalid UUID') -> None:
super().__init__(status_code, detail)
raise WrongUUIDError( # should be default
"Wrong uuid", error_response=self.error_response
) from e
Because of that:
To recap, the problem you noticed is that Python built-in errors are raised which results in 5xx. As those are request-response errors, they can be handled by the framework. The only thing that has to be done is changing existing errors to What do you think? |
I had a slight concern that raising as an HTTPException would make it hard to customize the response on user side, but I think most apps would define their own error handling anyway, and this would integrate it nicely along with Starlette and such errors. That approach should be sufficient, and indeed simpler here too. |
My attempts to implement this based on HTTPException failed, for the exact same reason for the original implementation.
The reason for this is, again from Starlette documentation:
Due to this design, anything that is raised from a middleware will only bubble up to the The current implementation is correct. |
@hhamana I remember about your PR but I'm currently overwhelmed with non-side-projects responsibilities. I'm grateful for your contribution but I can't look into it right now. Sorry for that. |
I still don't like this optional response here and there but I think it is a must. I was playing with your branch and indeed I think what you did is the only way to handle plugin (middleware) error. This PR looks really good. Thank you for your contribution and active discussion (and patience :D). |
Thank you very much. |
This PR fixes 2 issues:
The exact error is customizable from user code, but provides a default 400 response with empty body.
Implemented on both ContextMiddleware and RawContextMiddleware.