It would be helpful and more flexible to allow raising a custom exception in query_depth_limiter
when the max depth has been reached.
The QueryDepthLimiter
extension raises a generic GraphQLError
when it reaches the max depth.
It would be helpful to allow users to raise a custom exception, e.g. your own QueryDepthLimitReachedError
, so you can provide your own messaging, your own error extensions/codes, etc.
The simplest idea would be to allow passing an optional exception class in the constructor, e.g.
def __init__(
self,
max_depth: int,
ignore: Optional[List[IgnoreType]] = None,
callback: Optional[Callable[[Dict[str, int]], None]] = None,
exception_class: Optional[Type[GraphQLError]] = GraphQLError
):
validator = create_validator(max_depth, ignore, callback, exception_class)
super().__init__([validator])
# ...
if depth_so_far > max_depth:
context.report_error(
exception_class(
f"'{operation_name}' exceeds maximum operation depth of {max_depth}",
[node],
)
)
Or passing in a callable, replacing the call to initialize the exception, so that users can be more flexible, e.g.
def __init__(
self,
max_depth: int,
ignore: Optional[List[IgnoreType]] = None,
callback: Optional[Callable[[Dict[str, int]], None]] = None,
get_exception: Optional[Callable[[str, int, Node], Type[GraphQLError]]] = None,
):
validator = create_validator(max_depth, ignore, callback)
super().__init__([validator])
# ...
if depth_so_far > max_depth:
error = None
if get_exception:
error = get_exception(operation_name, max_depth, depth_so_far, node)
else:
error = GraphQLError(
f"'{operation_name}' exceeds maximum operation depth of {max_depth}",
[node],
)
context.report_error(error)
Alternatively, if the sub-methods in this class were functions or class methods on the MaxQueryDepthExtension
class, you could overload it like this (and have the extension call to self.get_exception
, though since the extension already takes in arguments in the constructor, this may not make as much sense. Or (though less flexible), setting the exception class on the extension
class MyMaxQueryDepthExtension(MaxQueryDepthExtension):
@classmethod
def get_exception(operation_name: str, max_depth: int, depth_so_far:int, node: Node) -> Type[GraphQLError]:
return MyCustomException()
or
class MyMaxQueryDepthExtension(MaxQueryDepthExtension):
exception = MyCustomException
If this seems reasonable and one of the options is agreed upon, I can take first pass at implementing it. However, I understand if this falls into a "constructor arg creep" where we just keep adding new args to the constructor for every new idea.
Thank you!
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too