Выбор схемы валидации на основе содержимого сообщения#
Допустим ситуацию, когда выбор схемы валидации, по которой необходимо валидировать сообщения, зависит от содержимого сообщения. Для примера рассмотрена валидация JSON-сообщения, приходящего в запросе.
Создайте две схемы валидации:
sel_schema_1.json:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"lastname": {
"type": "string"
},
"firstname": {
"type": "string"
},
"phone": {
"type": "string"
},
"version": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"lastname", "firstname", "version"
]
}
sel_schema_2.json:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"lastname": {
"type": "string"
},
"firstname": {
"type": "string"
},
"phone": {
"type": "string"
},
"version": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"lastname", "firstname", "version", "phone"
]
}
Как видно, две схемы отличаются только обязательностью свойства phone.
Создайте сервис, который, в зависимости от значения свойства version в объекте запроса, будет валидировать запрос либо по первой, либо по второй схеме. Если ни первая, ни вторая схема не выбрана, то запрос будет блокирован.
Добавьте в конфигурацию профиля chains еще один сервис:
- id: 4
allowed_queries:
- method: post
url: /balancer$
listen:
- port: 20204
modifiers:
set_output_headers:
- headers:
- version $clj_version
- failed-condition $clj_condition_failed
- expected $clj_condition_expected_value
- value $clj_condition_current_value
chains:
request_chains:
- actions:
- action: JsonPathExtractToVars
params:
expressions:
- path: $.version
var: clj_version
- action: JsonValidation
conditions:
- {var: $clj_version, val: "v1", operator: "="}
params:
validation_schema: {type: file, path: schemas/sel_schema_1.json}
- action: JsonValidation
conditions:
- {var: $clj_version, val: "v2", operator: "="}
params:
validation_schema: {type: file, path: schemas/sel_schema_2.json}
- action: ConditionChecker
params:
rules:
- {var: $clj_version, val: "v1,v2", operator: "IN"}
message: $clj_request_body
upstream_group_id: 1
upstream_groups:
- id: 1
servers:
- server: 127.0.0.1:30001
rewrite_uri:
- from: /balancer
to: /test
Полученная конфигурация:
Существует четыре независимые цепочки действий — в первой попытаемся извлечь из приходящего объекта свойство version и поместить его в переменную clj_version. Далее идут две цепочки для валидации сообщения в зависимости от результата проверки условия на значение версии. И наконец, четвертая цепочка состоит из единственного корневого действия ConditionChecker, который блокирует выполнение запроса, в том случае, если значение версии ни v1, ни v2. Также был добавлен вывод значений переменных в заголовки ответа клиента со значениями версии, невыполненного условия, ожидаемого и реальных значений. Три последних переменных будут заполнены, если действие ConditionChecker вернет отрицательный результат.
Скопируйте обе схемы в каталог /sowa/profile_storage/custom/chains/schemas, остановите, сконфигурируйте и запустите профиль.
Проверка работоспособности:
Отправьте запрос соответствующий версии 1:
bash-4.2$ curl -v http://localhost:20204/balancer --data '{"version": "v1", "lastname": "Ivanov", "firstname": "Ivan"}'Получен положительный ответ:

Отправьте запрос, соответствующий версии v2, но без обязательного свойства phone:
bash-4.2$ curl -v http://localhost:20204/balancer --data '{"version": "v2", "lastname": "Ivanov", "firstname": "Ivan"}'Запрос заблокирован:

Отправьте запрос с неподдерживаемым значением version:
bash-4.2$ curl -v http://localhost:20204/balancer --data '{"version": "v3", "lastname": "Ivanov", "firstname": "Ivan"}'Запрос заблокирован:
