-
-
Notifications
You must be signed in to change notification settings - Fork 544
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
Improve extensions error handling #3217
Improve extensions error handling #3217
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #3217 +/- ##
==========================================
+ Coverage 96.48% 96.49% +0.01%
==========================================
Files 509 509
Lines 32703 32862 +159
Branches 5404 5421 +17
==========================================
+ Hits 31552 31711 +159
Misses 940 940
Partials 211 211 |
CodSpeed Performance ReportMerging #3217 will improve performances by 13.87%Comparing Summary
Benchmarks breakdown
|
Just to make sure we're on the same page: In its current state this PR does not change the current mechanism, since it's only removing an unnecessary "fallback"
Yup, pretty straightforward changes. Making sure they're covered by tests this time. |
32331a0
to
cbebf5e
Compare
cbebf5e
to
0379a33
Compare
Thanks for adding the Here's a preview of the changelog: Starting with this release, any error raised from within schema This corresponds to the way we already handle field extension errors This is particular useful for schema extensions performing checks early class MaxQueryLengthExtension(SchemaExtension):
MAX_QUERY_LENGTH = 8192
async def on_operation(self):
if len(self.execution_context.query) > self.MAX_QUERY_LENGTH:
raise StrawberryGraphQLError(message="Query too large")
yield Here's the tweet text:
|
# only return a sanitised version to the client. | ||
process_errors(result.errors, execution_context) | ||
|
||
except (MissingQueryError, InvalidOperationTypeError) as e: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two exceptions get special handling by our view integrations and enables them to return appropriate status codes. For context:
strawberry/strawberry/http/sync_base_view.py
Lines 198 to 209 in d6bd38d
try: | |
result = self.execute_operation( | |
request=request, | |
context=context, | |
root_value=root_value, | |
) | |
except InvalidOperationTypeError as e: | |
raise HTTPException( | |
400, e.as_http_error_reason(request_adapter.method) | |
) from e | |
except MissingQueryError as e: | |
raise HTTPException(400, "No GraphQL query found in the request") from e |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that this solves the problem for now. However, I doubt that this is a long term solution due to the specificity of re-raising only specific exceptions. We should try to abstract that into an exception -> status code or modified response or graphQL error "middleware/exception filter" as a follow up to this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
something like an OperationError
? 😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's do in another PR/refactoring 😊
/pre-release |
Pre-release👋 Pre-release 0.220.0.dev.1709543239 [e3b40c0] has been released on PyPi! 🚀 poetry add strawberry-graphql==0.220.0.dev.1709543239 |
After testing this compared to the functionality of #3256. It seems like this PR is more verbose than I'd like in best case, as seen below |
Thanks for testing the pre-release! This PR currently wraps all raised errors in a |
/pre-release |
/pre-release |
/pre-release |
I've merged main into this, but something has changed 😊 I'll take a proper look at this in the following days |
@@ -721,7 +725,7 @@ def ping(self) -> str: | |||
@pytest.mark.parametrize( | |||
("failing_hook", "expected_hooks"), | |||
( | |||
("on_operation_start", set()), | |||
("on_operation_start", {2, 3, 4, 5, 6, 7}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@erikwrede do you think this makes sense?
we run all the hooks even if the execution stops?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mmh, looking at the current failure it looks like what we were trying to do is not working as I though
we can't stop an operation from an extension if we catch all exceptions, unless I'm missing something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you so much for this, sorry it took so long to do this 😊
This PR brings schema extension error handling in line with field extension and resolver error handling.
Description
This PR alters schema extension error handling so that any error raised from within schema
extensions will abort the operation and is added to the execution result.
Before, most errors (including Strawberry/graphql-core GraphQLErrors) would cause an internal server error.
Furthermore, these changes enable extensions (e.g. the one described in #3204) to abort operations early in a requests lifecycle which was not easily possible before.
Types of Changes
Issues Fixed or Closed by This PR
Checklist