mirror of
https://github.com/graphql-python/graphene-django.git
synced 2025-07-09 15:52:26 +03:00
Merge 1b78a6f638
into f02ea337a2
This commit is contained in:
commit
d73c3f3eff
49
docs/error-masking.rst
Normal file
49
docs/error-masking.rst
Normal file
|
@ -0,0 +1,49 @@
|
|||
Custom GraphQL Error Masking
|
||||
============================
|
||||
|
||||
This project includes a custom error formatting function for GraphQL
|
||||
responses that masks sensitive error details from clients.
|
||||
|
||||
Purpose
|
||||
-------
|
||||
|
||||
- Prevent exposing internal error details for security and user experience.
|
||||
- Allow whitelisting of exception classes that should be exposed as-is.
|
||||
- Return a generic error message for all other exceptions.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
You can control the behavior using the ``GRAPHENE_ERRORS`` setting in your
|
||||
Django settings file under the ``GRAPHENE`` namespace:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
GRAPHENE = {
|
||||
"GRAPHENE_ERRORS": {
|
||||
"MASK_EXCEPTIONS": True, # Enable or disable masking
|
||||
"ERROR_MESSAGE": "A custom error message.", # Defaults to "Something went wrong. Please try again later."
|
||||
"WHITELISTED_EXCEPTIONS": [
|
||||
"ValidationError", # Whitelist by class name
|
||||
"django.core.exceptions.ValidationError", # Whitelist by full module path
|
||||
"myapp.custom_exceptions.MyCustomException", # Custom exception whitelist by full path
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
Behavior
|
||||
--------
|
||||
|
||||
- If ``MASK_EXCEPTIONS`` is False, all errors are returned fully formatted.
|
||||
- If True, errors not in the whitelist will return only the generic message.
|
||||
- Whitelisted exceptions are returned with full error details.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The masking is automatically applied to the error responses of GraphQL
|
||||
queries and mutations through a custom error formatter method.
|
||||
|
||||
You can modify or extend the whitelisted exceptions as needed to suit your
|
||||
project's error handling policy.
|
||||
|
|
@ -46,6 +46,7 @@ DEFAULTS = {
|
|||
"ATOMIC_MUTATIONS": False,
|
||||
"TESTING_ENDPOINT": "/graphql",
|
||||
"MAX_VALIDATION_ERRORS": None,
|
||||
"GRAPHENE_ERRORS": {},
|
||||
}
|
||||
|
||||
if settings.DEBUG:
|
||||
|
|
|
@ -228,9 +228,32 @@ class GraphQLView(View):
|
|||
|
||||
if execution_result.errors:
|
||||
set_rollback()
|
||||
response["errors"] = [
|
||||
self.format_error(e) for e in execution_result.errors
|
||||
]
|
||||
|
||||
def safe_format(error):
|
||||
config = getattr(graphene_settings, "GRAPHENE_ERRORS", {})
|
||||
mask_exceptions = config.get("MASK_EXCEPTIONS", False)
|
||||
error_message= config.get("ERROR_MESSAGE", "Something went wrong. Please try again later.")
|
||||
whitelist = config.get("WHITELISTED_EXCEPTIONS", [])
|
||||
|
||||
if not mask_exceptions:
|
||||
return self.format_error(error)
|
||||
|
||||
original_error = getattr(error, "original_error", None)
|
||||
if not original_error:
|
||||
return {"message": error_message}
|
||||
|
||||
error_class = type(original_error)
|
||||
class_name = error_class.__name__
|
||||
full_path = f"{error_class.__module__}.{class_name}"
|
||||
|
||||
if class_name in whitelist or full_path in whitelist:
|
||||
return self.format_error(error)
|
||||
|
||||
formatted = self.format_error(error)
|
||||
formatted["message"] = error_message
|
||||
return formatted
|
||||
|
||||
response["errors"] = [safe_format(e) for e in execution_result.errors]
|
||||
|
||||
if execution_result.errors and any(
|
||||
not getattr(e, "path", None) for e in execution_result.errors
|
||||
|
|
Loading…
Reference in New Issue
Block a user