GraphQLRequestValidation#

Действие GraphQLRequestValidation предназначено для валидации запроса GraphqQL.

На текущий момент реализованы:

  • Парсинг graphql запроса из тела (json|graphql в зависимости от content-type) и параметров url запроса;

  • Валидация по схеме;

  • Запрет introspection query (включен всегда);

  • Возможность ограничения запроса по глубине.

Парсинг запроса происходит согласно рекомендации Serving over HTTP (оригинал на graphql.org) если следовать примеру ниже.

GraphQL запрос состоит из 3 частей:

  • query — запрос(ы);

  • operationName — наименование операции из query, которая запрашивается клиентом;

  • variables — список значений переменных, использующихся в query.

Поддерживаемые варианты передачи данных параметров:

  1. В параметрах url.

    Используется для get запросов.

    http://host:port/graphql?query=...&variables=...&operationName=...
    
  2. В теле запроса в JSON обертке.

    Используется для POST запросов.

    http://host:port/graphql
     
    {
      "query": "...",
      "operationName": "...",
      "variables": { "myVariable": "someValue", ... }
    }   
    
  3. В теле запроса в JSON обертке, при этом query - в параметрах url.

    Используется для POST запросов.

    http://host:port/graphql?query=...
     
    {
      "operationName": "...",
      "variables": { "myVariable": "someValue", ... }
    }
    
  4. В теле запроса только query без json обертки.

    Используется для POST запросов, когда не требуется передавать ни operationName, ни variables.

Для того чтобы обеспечить возможность настройки parsing(s), введены следующие параметры:

Название

Обязательность

Допустимые значения

Описание

input_is_url_params

-

true/false

Необязательный параметр, сигнализирующий о том, что message - urlencoded строка. Используется для GET запросов, когда на вход цепочке идут аргументы запроса из url. Значение по умолчанию: false.

query_can_be_in_url

-

true/false

Необязательный параметр, сигнализирующий о том, что необходимо разобрать не только message, но также аргументы запроса из url. Используется для POST запросов, когда на вход цепочке идет тело сообщение, но также в параметрах url может быть query. Значение по умолчанию: false.

При этом наличие/отсутствие json обертки определяется по заголовку сontent-type.

По умолчанию параметры query, variables, operationName берутся из одноименных полей.

В случае, если названия полей отличаются, можно использовать следующие параметры parsing(s):

Название

Обязательность

Допустимые значения

Описание

queryField

-

строка

Название поля с query. Значение по умолчанию: query

operationNameField

-

строка

Название поля с operationName. Значение по умолчанию: operationName

variablesField

-

строка

Название поля с variables. Значение по умолчанию: variables

Параметры валидации:

Название

Обязательность

Допустимые значения

Описание

validation_schema

+

Элемент вида {type: file, path: путь}

Обязательный параметр, определяющий относительный путь к схеме валидации от каталога ресурсов профиля, задается в виде: {type: file, path: путь_к_схеме}.

extended_scalars

-

Элемент вида {type: file, path: путь}

Необязательный параметр, определяющий относительный путь к yml файлу описания расширенных скаляров от каталога ресурсов профиля.

max_query_depth

-

Положительное число

Необязательный параметр. В случае, если необходима проверка на максимальную глубину запроса, необходимо задать этот параметр.

max_query_amount

-

Положительное число

Необязательный параметр. В случае, если необходима проверка на максимальную ширину запроса, необходимо задать этот параметр.

Рассмотрим пример:

chains:
  request_chains:
    - message: $clj_request_body
      actions:
        - action: GraphQLRequestValidation
          params:
            validation_schema: { type: file, path: schemes/graphql_max_depth/small_schema_with_mutation.graphqls }
            extended_scalars: { type: file, path: schemes/extended_scalars.yml }
            max_query_amount: 1
            max_query_depth: 4           validation_schema: {type: file, path: schemes/small_schema.graphqls}
          conditions:
            - {var: $clj_request_body, operator: "!=", val: ""}
    - message: $args
      actions:
        - action: GraphQLRequestValidation
          conditions:
            - {var: $clj_request_body, operator: "=", val: ""}
          params:
            validation_schema: { type: file, path: schemes/graphql_max_depth/small_schema_with_mutation.graphqls }
            extended_scalars: { type: file, path: schemes/extended_scalars.yml }
            input_is_url_params: true
            max_query_amount: 1
            max_query_depth: 4

В приведенном примере валидация осуществляется в зависимости от наличия тела запроса.

  1. В случае непустого тела запроса (актуально для POST/PUT):

    • задается параметр

      validation_schema — путь к схеме валидации;

    • по умолчанию параметры

      input_is_url_params = false

      query_can_be_in_url = true.

    Этот случай покрывает варианты parsing(s) 2,3,4.

  2. В случае пустого тела запроса (актуально для GET):

    • задаются параметры

      validation_schema — путь к схеме валидации;

      input_is_url_params = true.

    Этот случай покрывает вариант parsing(s) 1.

Рассмотрим подробнее вопрос описания расширенных скаляров:

По умолчанию graphql поддерживает 5 базовых типов: String, Int, Float, Boolean, ID (basic-types).

Также были добавлены скаляры, описанные в библиотеке graphql-java-extended-scalars (полный список case sensitive:Locale, Object, JSON, Time, Date, DateTime, Url, Char, Byte, Long, Short, BigDecimal, PositiveInt, NonPositiveFloat, BigInteger, NegativeFloat, PositiveFloat, NonNegativeFloat, NonNegativeInt, NonPositiveInt, NegativeInt, Currency, CountryCode, UUID, LocalTime).

В случае, если необходимо добавить собственное наименование для стандартного типа, или же задать Regex для строкового типа, можно задать файл с описанием расширенных скаляров, например:

- name: Map
  base_scalar: JSON
- name: LocalDate
  base_scalar: Regex
  pattern: ^\d{4}-\d{2}-\d{2}$
- name: LocalDateTime
  base_scalar: Regex
  pattern: \d{4}-[01]\d-[0-3]\d\s[0-2]\d((:[0-5]\d)?){2}

В случае с новым именем для скаляра, необходимо в поле name указать имя нового скаляра, в base_scalar - имя базового скаляра.

В случае с заданием регулярного выражения для строкового типа необходимо в поле name указать имя нового скаляра, в base_scalar - Regex, в pattern - регулярное выражение.