Вопрос или проблема
У меня есть сервер Nginx с реверс-прокси. Я просто хотел узнать, возможно ли перенаправить запрос в Nginx на основе типа контента запроса?
Сейчас я проверяю URL на наличие ключевого слова и на основе этого перенаправляю запрос. Это похоже на следующее:
location ~*/(keyword){
proxy_pass http://127.0.0.1:6565;
}
Но теперь у меня есть другой URL с тем же ключевым словом. Однако тип контента запроса будет 'application/json'
, и я должен перенаправить этот запрос на порт 8080. Можно ли различить эти два URL? Я использую Nginx 1.6.2.
Спасибо.
Это запутанная проблема, потому что значение заголовка Accept
не обязательно является одной записью, а вместо этого представляет собой список типов медиа с “качественными” значениями, которые необходимо сопоставить с доступными представлениями ресурсов для определения того, какой тип отправить обратно.
Существуют возможные способы обойтись с заявлениями if
и сопоставлением регулярных выражений по содержимому заголовка Accept
(“If is Evil” не считая), но для надежного выполнения вам почти всегда придется написать собственный модуль для выполнения сопоставления (вероятно, против карты). Существует сторонний модуль AcceptLanguage, который может содержать полезный код для начала.
Редактировать на основе обновленного вопроса
Если все, что вы хотите сделать, это перенаправить на основе типа контента тела запроса, то жизнь становится гораздо проще. Я бы настроил карту типов контента к бэкенду, а затем использовал бы эту карту для преобразования переменной $http_content_type
в бэкенд для отправки запроса. Убедитесь, что вы обрабатываете (и проверяете!) “исключительные” случаи, такие как “не отправлен тип контента” и “отправлен тип контента, который мы не ожидали”.
Ответ или решение
Для изменения правил перенаправления запросов в Nginx на основе Content-Type запроса, это действительно возможно, используя переменные и директивы Nginx. В вашем случае, раз у вас есть запрос на перенаправление в зависимости от типа контента, можно воспользоваться директивой map
, которая призвана сопоставлять значения переменных с определенными результатами.
Вот подробное руководство о том, как вы можете организовать перенаправления с учетом Content-Type запросов:
Шаг 1: Определение карты
Сначала вам нужно создать карту, которая будет сопоставлять Content-Type
с соответствующим бэкендом. Например, если у вас есть два бэкенда, один на port 6565
для обычных запросов и другой на port 8080
для application/json
, вам нужно это настроить следующим образом:
map $http_content_type $backend {
default "http://127.0.0.1:6565";
"application/json" "http://127.0.0.1:8080";
}
В этой конфигурации используется $http_content_type
как ключ для карты. Если передан Content-Type application/json
, запрос будет направлен на порт 8080. Во всех остальных случаях он будет перенаправляться на порт 6565.
Шаг 2: Настройка location
Теперь вы можете настроить вашу блокировку location
, чтобы использовать значение карты для проксирования запросов. Вот как вы можете это сделать:
server {
listen 80;
location ~*/(keyword) {
proxy_pass $backend; # Используем значение из карты
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Шаг 3: Обработка исключительных случаев
Важно также учесть случаи, когда заголовок Content-Type
не установлен или имеет неожиданное значение. Можно добавить дополнительные настройки или обработчики для таких случаев. Например:
error_page 404 = @handle_error;
location @handle_error {
# Log the error or handle it accordingly
return 400 "Unsupported Content-Type";
}
Такой код позволит вам обрабатывать запросы, когда Content-Type
неуместен.
Заключение
Используя приведённый выше метод с map
и proxy_pass
, вы сможете эффективно перенаправлять запросы на основе Content-Type
. Это решение эффективно отделяет логику запроса от обработки и позволяет поддерживать аккуратную и организованную конфигурацию Nginx. Пожалуйста, выполните тестирование после каждой правки, чтобы удостовериться, что всё функционирует как следует.
Эта конфигурация должна работать с Nginx версии 1.6.2 и выше, и учтите, что, возможно, вам будет полезно обновить Nginx до более новой версии, поскольку более свежие релизы могут содержать улучшения и исправления по безопасности.
Если у вас возникнут дополнительные вопросы или потребуется уточнение, не стесняйтесь спрашивать!