Постобработка ошибок#
До сих пор, все ошибки транслировались клиенту "as is", однако зачастую необходимо переопределить либо код статуса ответа с ошибкой, либо тело сообщения об ошибке. Для этого используется функциональность постобработки.
Допустим, необходимо переопределить стандартную ошибку с backend "404 Not Found" в ответ клиенту со статусом 500 и телом ответа:
{
"message": "На стороне запрашиваемого сервера произошла ошибка"
}
Объявим сервис override_error:
profile: proxy_rewrite
version: 2.0.3
system:
wrk_count: 1
conn_count: 4096
optional:
log_level: error
service:
service_http_proxy:
- id: rewrite_service
name: service_2
url: ^/bye
upstream_group_id: back_1
upstream_groups:
- id: back_1
servers:
- server: 127.0.0.1:10012
rewrite_uri:
- from: /
to: /notFound
allowed_queries:
- method: get
listen:
- port: 11102
postprocessors:
postprocessor_error:
code:
- 404
custom_pattern_file: templates/pattern.json
rules_file: rules/postrules.yml
content_type: application/json;charset=UTF-8
handle_upstream_errors: true
Здесь видно секцию postprocessors, в которой, собственно, и было объявлено поведение для постобработки.
Здесь:
code - список кодов состояния, для которых будет выполняться переопределение ответов;
custom_pattern_file - файл шаблона тела ответа. Вместо custom_pattern_file может использоваться параметр pattern_file, в котором можно указывать один из предопределенных шаблонов, в этом случае указывается имя без пути;
rules_file - файл с правилами, формат правил описан в разделе "Создание файла c правилами";
content_type - значение заголовка content-type для генерируемого ответа;
handle_upstream_errors - указывает, обрабатывать ли ошибки, пришедшие с backend.
Создадим файл шаблона ответа pattern.json:
{
"message": "{error_message}"
}
Здесь в фигурных скобках используется подстановка, которая в зависимости от того, какое правило отработает в runtime, будет заменено на значение, определенное в соответствующем правиле.
Создадим файл с правилами postrules.yml, в котором зададим следующую конструкцию:
rules:
- condition:
- var: upstream_response_state
operator: "="
val: 404
replacements:
- pattern: error_message
val: "На стороне запрашиваемого сервера произошла ошибка"
status: 500
Здесь задается условие, что если с backend ответ вернулся со статусом 404 (переменная upstream_response_state), то заменяем в шаблоне {error_message} на сообщение "На стороне запрашиваемого сервера произошла ошибка" и возвращаем ответ со статус кодом = status.
Далее следует создать профиль, каталоги под ресурсы в ресурсном каталоге профиля, и скопировать туда созданные выше ресурсы.
[sowacfg@tkle-ish0038 proxies]$ sowa-config --add-profile override_error
Profile "override_error" was successfully created
[sowacfg@tkle-ish0038 proxies]$ mkdir /sowa/profile_storage/custom/override_error/templates
[sowacfg@tkle-ish0038 proxies]$ mkdir /sowa/profile_storage/custom/override_error/rules
[sowacfg@tkle-ish0038 proxies]$ cp pattern.json /sowa/profile_storage/custom/override_error/templates/
[sowacfg@tkle-ish0038 proxies]$ cp postrules.yml /sowa/profile_storage/custom/override_error/rules/
После чего необходимо сконфигурировать профиль, запустить его и попытаться отправить запрос:
[sowacfg@tkle-ish0038 proxies]$ curl -v http://localhost:11102/bye
* About to connect() to localhost port 11102 (#0)
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 11102 (#0)
> GET /bye HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:11102
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
< Date: Wed, 07 Apr 2021 12:24:48 GMT
< Content-Type: application/json; charset=UTF-8
< Content-Length: 117
< Connection: keep-alive
< Server: SOWA
{
"На стороне запрашиваемого сервера произошла ошибка"
* Connection #0 to host localhost left intact