Как остановить автоматическое перенаправление 301 в nginx, когда в URI отсутствует конечный слэш?

Вопрос или проблема

Каждый раз, когда я пытаюсь открыть 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 или отключив некоторые функции.

Решение проблемы

  1. Использование точного совпадения: Вы можете определить 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;
       }
    }
  2. Отключение относительного редиректа: Можно отключить абсолютные редиректы на уровне всего сервера, добавив директиву 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

Регулярно проверяйте логи вашего сервера, чтобы убедиться, что изменения работают корректно и не вызывают новых проблем.

Оцените материал
Добавить комментарий

Капча загружается...