Постобработка ошибок#

До сих пор, все ошибки транслировались клиенту "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