Динамические модификации заголовков

Как изменить заголовки запроса перед отправкой на upstream и заголовки ответа перед возвратом клиенту.

Что это

Динамические модификации заголовков — изменение HTTP-заголовков на уровне Application Delivery Controller.

Система может добавить, удалить или перезаписать заголовки запроса и ответа. Для значений заголовков можно использовать константы и переменные, например, адрес нашей системы, параметры запроса или значения, полученные при обработке URI.

Как работает

  1. Клиент отправляет запрос.

  2. Наша система получает запрос и сопоставляет его с Route, в котором настроены плагины для изменения заголовков: proxy-rewrite, response-rewrite или оба сразу.

  3. Если настроен proxy-rewrite, система изменяет заголовки запроса перед отправкой на upstream.

    Плагин может добавить заголовок через headers.add, перезаписать через headers.set или удалить через headers.remove. Если нужно изменить заголовок Host, используется отдельный атрибут host.

  4. Upstream получает запрос уже с изменёнными заголовками.

  5. Upstream возвращает ответ.

  6. Если настроен response-rewrite, система изменяет заголовки ответа перед возвратом клиенту.

    Плагин может добавить, перезаписать или удалить response headers. Также можно задать условия через vars, чтобы изменения применялись только к части ответов, например только к ответам со статусом 200.

  7. Клиент получает ответ уже с изменёнными заголовками.

Когда пригодится

Предположим, у вас есть публичный API, а внутренний бэкенд ожидает служебные заголовки: версию API, источник запроса или технический маркер, по которому он выбирает обработчик.

Передавать эти заголовки от клиента неудобно и небезопасно: клиент может не знать внутреннюю схему или подставить неверное значение. Поэтому вы добавляете proxy-rewrite и настраиваете заголовки, которые система сама передаст на upstream.

В обратную сторону задача может быть другой: например, бэкенд возвращает внутренний заголовок X-Internal-Service, который не должен уходить клиенту. Или, наоборот, к каждому ответу от бэкенда нужно добавить публичный заголовок Cache-Control.

Для этого вы добавляете response-rewrite. В результате upstream получает нужные request headers, а клиент получает только те response headers, которые должны быть видны снаружи.

Какие плагины используются

  • proxy-rewrite — изменяет заголовки запроса перед отправкой на upstream,

  • response-rewrite — изменяет заголовки ответа перед возвратом клиенту.

Атрибуты плагина proxy-rewrite для изменения заголовков

Атрибут Тип Обязательный Значение по умолчанию Допустимые значения Что задаёт

host

string

Нет

Значение заголовка Host, с которым запрос будет отправлен на upstream.

headers

object

Нет

add, remove, set

Действия с заголовками запроса. Можно добавить, удалить или перезаписать заголовки перед отправкой запроса на upstream.

headers.add

object

Нет

Константа, NGINX variables или значения из regex_uri, например $1

Добавляет значения к заголовкам запроса. Если заголовок уже есть, новое значение добавляется к существующему: итоговое значение выглядит как v1,v2, где v1 — значение из плагина, а v2 — значение из исходного запроса.

headers.set

object

Нет

Константа, NGINX variables или значения из regex_uri, например $1

Устанавливает значения заголовков запроса. Если заголовок уже есть, его значение будет перезаписано. Не используйте headers.set для настройки Host: для этого есть отдельный атрибут host.

headers.remove

array
[string]

Нет

Имена заголовков

Удаляет указанные заголовки из запроса перед отправкой на upstream.

Атрибуты плагина response-rewrite для изменения заголовков

Атрибут Тип Обязательный Значение по умолчанию Допустимые значения Что задаёт

headers

object

Нет

add, remove, set

Действия с заголовками ответа. Можно добавить, удалить или перезаписать заголовки перед возвратом ответа клиенту.

headers.add

array
[string]

Нет

Строки с именем и значением заголовка

Добавляет заголовки к ответу. Значение может быть константой или NGINX variable.

headers.set

object

Нет

Константа или NGINX variable

Устанавливает значения заголовков ответа. Если заголовок уже есть, его значение будет перезаписано.

headers.remove

array
[string]

Нет

Имена заголовков

Удаляет указанные заголовки из ответа перед возвратом клиенту.

vars

array
[array]

Нет

Условия в формате lua-resty-expr

Условия, при которых будет выполнено изменение ответа. Например, можно применять настройки только к ответам с определённым HTTP-статусом.

Что важно учесть

В обоих плагинах headers.add и headers.set работают по-разному. headers.add добавляет значение к существующему заголовку, а headers.set перезаписывает его.

В обоих плагинах, если в headers указано несколько действий, они выполняются в таком порядке: add, затем remove, затем set.

В proxy-rewrite для изменения Host в запросе используйте атрибут host, а не headers.set.

response-rewrite может изменять ответы upstream и ответы, сформированные Application Delivery Controller. Если изменения должны применяться не ко всем ответам, задайте условия в vars.

Как подключить плагин

Через API

Плагины можно добавить к Route через Admin API. Для этого отправьте запрос на создание или обновление Route:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "id": "route-id",
    "uri": "/example",
    "plugins": {
      "proxy-rewrite": {
        "...": "ваши настройки плагина"
      },
      "response-rewrite": {
        "...": "ваши настройки плагина"
      }
    },
    "upstream": {
      "...": "ваши настройки upstream"
    }
  }'

Здесь id — идентификатор Route, uri — путь, по которому запрос попадает в Route, plugins.proxy-rewrite и другие объекты внутри plugins содержат конфигурацию плагинов, а upstream — настройки бэкенд-серверов.

Через UI

  1. Откройте раздел Маршруты и нажмите + Добавить.

  2. В настройках маршрута (Route) перейдите в раздел Плагины.

  3. Нажмите + Добавить и выберите нужный плагин.

  4. Укажите конфигурацию плагина как JSON-объект.

  5. Аналогично добавьте и настройте второй плагин, если нужно.

  6. Сохраните созданный маршрут (Route). Он будет добавлен с подключённым плагином.

Пример конфигурации плагина

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

Исходный запрос клиента:

GET /api/v1/orders/ORD-1001
X-Debug-Token: test

Настройка плагинов proxy-rewrite и response-rewrite:

{
  "plugins": {
    "proxy-rewrite": {
      "headers": {
        "set": {
          "X-Api-Version": "v2",
          "X-Request-Source": "gateway"
        },
        "remove": [
          "X-Debug-Token"
        ]
      }
    },
    "response-rewrite": {
      "headers": {
        "set": {
          "Cache-Control": "no-store",
          "X-Gateway-Policy": "public-api"
        },
        "remove": [
          "X-Internal-Service"
        ]
      }
    }
  }
}

После обработки upstream получит запрос с такими заголовками:

GET /api/v1/orders/ORD-1001
X-Api-Version: v2
X-Request-Source: gateway

Заголовок X-Debug-Token будет удалён перед отправкой запроса на upstream.

Если upstream вернёт такой ответ:

HTTP/1.1 200 OK
X-Internal-Service: orders-core
Content-Type: application/json

Клиент получит ответ без внутреннего заголовка, но с заголовками, которые добавила система:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
X-Gateway-Policy: public-api

Так proxy-rewrite управляет заголовками запроса к upstream, а response-rewrite — заголовками ответа клиенту.