Вопрос или проблема
Каждый раз, когда я пытаюсь открыть foobar.com/test в браузере, nginx, похоже, перенаправляет (301) клиента на foobar.com/test/. Такое поведение неприемлемо. Проксируемый сервер – это удаленный веб-сервер Apache. Я пробовал прямые обращения к серверу Apache (без прокси), и он не перенаправляет клиента.
С учетом конфигурации сервера nginx ниже, есть идеи, как мне это решить?
server {
listen 80;
server_name fooBar.com;
location /test {
proxy_redirect off;
proxy_pass http://1.1.1.1:80/;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_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;
}
location /test/ {
proxy_redirect off;
proxy_pass http://1.1.1.1:80/;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_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;
}
}
Существует специальный вид обработки для этого сценария, согласно документации:
Если местоположение определено префиксной строкой, заканчивающейся символом слэша, и запросы обрабатываются одним из proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass или memcached_pass, то выполняется специальная обработка. В ответ на запрос с URI, равным этой строке, но без завершающего слэша, будет возвращено постоянное перенаправление с кодом 301 на запрашиваемый URI с добавленным слэшем. Если это не желательно, можно определить точное совпадение URI и расположения следующим образом:
location /user/ { proxy_pass http://user.example.com; } location = /user { proxy_pass http://login.example.com; }
(http://nginx.org/en/docs/http/ngx_http_core_module.html#location)
Из Stack Overflow > Nginx вызывает 301 перенаправление, если нет завершающего слэша:
В вашем блоке server { }
добавьте absolute_redirect off;
следующим образом:
server {
listen 80;
server_name localhost;
absolute_redirect off;
location /foo/ {
proxy_pass http://bar/;
}
}
Это исправление нужно применить всего один раз, вместо того чтобы вручную изменять множество ссылок.
Ответ или решение
Для остановки автоматического редиректа 301 при отсутствии конечного слеша в URI в конфигурации Nginx, вам необходимо внести несколько изменений в текущую настройку сервера. Приведенные ниже рекомендации помогут вам решить данную проблему, обеспечивая более гибкую обработку запросов и предотвращая нежелательные редиректы.
Анализ проблемы
При настройке Nginx, если вы указываете location
с окончанием на слеш (/
), Nginx автоматически выполняет редирект с кода 301, если запрос приходит без слеша на конце. Это поведение встроено в логику обработки, которую вы можете изменить, создав точное совпадение с URI или отключив некоторые функции.
Решение проблемы
-
Использование точного совпадения: Вы можете определить
location
с точным совпадением, используя оператор=
для URI без слеша. Это позволит обработать запрос без перенаправления.Пример:
server { listen 80; server_name fooBar.com; location = /test { proxy_pass http://1.1.1.1:80/; proxy_redirect off; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Host $http_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; } location /test/ { proxy_pass http://1.1.1.1:80/; proxy_redirect off; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Host $http_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; } }
-
Отключение относительного редиректа: Можно отключить абсолютные редиректы на уровне всего сервера, добавив директиву
absolute_redirect off;
, что позволит избежать нежелательной автоматизации редиректов для всех URI.Пример:
server { listen 80; server_name fooBar.com; absolute_redirect off; location /test { proxy_pass http://1.1.1.1:80/; proxy_redirect off; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Host $http_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; } location /test/ { proxy_pass http://1.1.1.1:80/; proxy_redirect off; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Host $http_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; } }
Заключение
После внесения указанных изменений в конфигурацию Nginx, автоматические редиректы 301 должны прекратиться, и ваша система будет обрабатывать запросы с использованием URI без конечного слеша должным образом. Оба решения — как с использованием location =
, так и отказ от абсолютных редиректов — являются эффективными и могут быть адаптированы в зависимости от специфики вашего проекта.
Рекомендации
После внесения изменений не забудьте перезапустить Nginx для применения новых конфигураций. Для этого выполните команду:
sudo systemctl restart nginx
Регулярно проверяйте логи вашего сервера, чтобы убедиться, что изменения работают корректно и не вызывают новых проблем.