2021-08-14 05:50:46 +03:00
Query Validation
2023-02-28 15:21:45 +03:00
================
2021-08-14 05:50:46 +03:00
GraphQL uses query validators to check if Query AST is valid and can be executed. Every GraphQL server implements
standard query validators. For example, there is an validator that tests if queried field exists on queried type, that
makes query fail with "Cannot query field on type" error if it doesn't.
To help with common use cases, graphene provides a few validation rules out of the box.
Depth limit Validator
2023-02-28 15:21:45 +03:00
---------------------
2021-08-14 05:50:46 +03:00
The depth limit validator helps to prevent execution of malicious
queries. It takes in the following arguments.
- `` max_depth `` is the maximum allowed depth for any operation in a GraphQL document.
- `` ignore `` Stops recursive depth checking based on a field name. Either a string or regexp to match the name, or a function that returns a boolean
- `` callback `` Called each time validation runs. Receives an Object which is a map of the depths for each operation.
2021-08-14 06:11:24 +03:00
Usage
2023-02-28 15:21:45 +03:00
-----
2021-08-14 05:50:46 +03:00
Here is how you would implement depth-limiting on your schema.
.. code :: python
2021-09-28 04:11:54 +03:00
2021-08-14 05:50:46 +03:00
from graphql import validate, parse
from graphene import ObjectType, Schema, String
from graphene.validation import depth_limit_validator
class MyQuery(ObjectType):
name = String(required=True)
schema = Schema(query=MyQuery)
2021-08-14 06:11:24 +03:00
# queries which have a depth more than 20
2021-08-14 05:50:46 +03:00
# will not be executed.
validation_errors = validate(
2021-09-29 15:43:08 +03:00
schema=schema.graphql_schema,
2021-08-14 05:50:46 +03:00
document_ast=parse('THE QUERY'),
rules=(
depth_limit_validator(
max_depth=20
),
)
)
2021-08-14 06:11:24 +03:00
Disable Introspection
---------------------
the disable introspection validation rule ensures that your schema cannot be introspected.
This is a useful security measure in production environments.
Usage
2023-02-28 15:21:45 +03:00
-----
2021-08-14 06:11:24 +03:00
Here is how you would disable introspection for your schema.
.. code :: python
2021-09-28 04:11:54 +03:00
2021-08-14 06:11:24 +03:00
from graphql import validate, parse
from graphene import ObjectType, Schema, String
from graphene.validation import DisableIntrospection
class MyQuery(ObjectType):
name = String(required=True)
schema = Schema(query=MyQuery)
# introspection queries will not be executed.
validation_errors = validate(
2021-09-29 15:43:08 +03:00
schema=schema.graphql_schema,
2021-08-14 06:11:24 +03:00
document_ast=parse('THE QUERY'),
rules=(
DisableIntrospection,
)
)
2021-08-14 05:50:46 +03:00
Implementing custom validators
------------------------------
All custom query validators should extend the `ValidationRule <https://github.com/graphql-python/graphql-core/blob/v3.0.5/src/graphql/validation/rules/__init__.py#L37> `_
base class importable from the graphql.validation.rules module. Query validators are visitor classes. They are
instantiated at the time of query validation with one required argument (context: ASTValidationContext). In order to
perform validation, your validator class should define one or more of enter_* and leave_* methods. For possible
enter/leave items as well as details on function documentation, please see contents of the visitor module. To make
validation fail, you should call validator's report_error method with the instance of GraphQLError describing failure
reason. Here is an example query validator that visits field definitions in GraphQL query and fails query validation
2021-08-14 06:11:24 +03:00
if any of those fields are blacklisted:
2021-08-14 05:50:46 +03:00
.. code :: python
2021-09-28 04:11:54 +03:00
2021-08-14 05:50:46 +03:00
from graphql import GraphQLError
from graphql.language import FieldNode
from graphql.validation import ValidationRule
my_blacklist = (
"disallowed_field",
)
def is_blacklisted_field(field_name: str):
2021-08-14 06:11:24 +03:00
return field_name.lower() in my_blacklist
2021-08-14 05:50:46 +03:00
class BlackListRule(ValidationRule):
def enter_field(self, node: FieldNode, *_args):
field_name = node.name.value
if not is_blacklisted_field(field_name):
return
self.report_error(
GraphQLError(
f"Cannot query '{field_name}': field is blacklisted.", node,
)
)