GraphQL로 쿼리를 실행하면 Query AST가 쿼리가 유효 하며 실행 가능한 상태인지 확인한다. 아래에 자주 사용되는 validator와 custom validator에 대해 소개한다.
추상 구문 트리(abstract syntax tree, AST)란?(위키백과 참고)
추상 구문 트리(abstract syntax tree, AST) by 위키백과
우리 서비스에 GraphQL을 도입할 지 말 지를 논의할 때 문제가 되었던 것 중 하나가 depth limit을 설정해야 하지 않냐는 것이었다. Depth Limit Validator를 이용하면 해결할 수 있겠다.
그런데... graphene-django에서 이를 적용하는 데에는 어려움이 있다고 한다. 해결 방법은 뒤에서 찾아보기로 한다.
이 validator에서 사용하는 arguments는 다음과 같다.
max_depth
ignore
callback
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)
# queries which have a depth more than 20
# will not be executed.
validation_errors = validate(
schema=schema.graphql_schema,
document_ast=parse('THE QUERY'),
rules=(
depth_limit_validator(
max_depth=20
),
)
)
enter_*
또는 leave_*
메소드가 반드시 정의되어야 한다.report_error
메소드를 호출해야 한다(가령, 클라가 해당 필드는 호출하지 못하도록 하려는 경우).report_error
메소드에 GraphQLError
인스턴스를 인자로 주어야 하는데 이 때 실패 이유를 표시해서 함께 호출하면 된다.아래 예시는 특정 필드가 블랙리스트에 포함된 경우 validation이 실패하도록 만든다.
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):
return field_name.lower() in my_blacklist
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,
)
)
위와 같은 방법으로 validation을 할 수도 있지만, 찾아보니 GraphQLError
를 사용하는 방법이 더 많이 언급된다.
예를 들어, Mutation에 대한 error_message를 주고 싶은 경우 아래와 같은 방법을 사용하면 된다.
from graphql import GraphQLError
...
raise GraphQLError(message="User name already exists", extensions={"code": 400})