Назад | Перейти на главную страницу

Почему Nginx не возвращает ошибку 404 для URL-адресов, начинающихся с вопросительного знака?

Я пытаюсь заставить работать правило перезаписи и обнаружил, что если URL-адрес начинается с вопросительного знака, Nginx не возвращает ошибку 404, как ожидалось. Вместо этого index.html, как определено в корневой директиве, обслуживается для всех URL-адресов, начинающихся с "?". (например. example.com/?page-does-not-exist работает для домашней страницы, но не должно)

Это делает невозможным перенаправление с example.com/?format=feed&type=rss -> example.com/rss.xml работает. Это для блога, перенесенного с Joomla на Jekyll.

Проще говоря, посещение example.com/123 возвращает 404, и посещение example.com/?123 не. Последний возвращает домашнюю страницу сайта по URL-адресу example.com?/123. (Нет файла или папки "123", поэтому запросы на них всегда должны завершаться ошибкой.)

Все работает отлично с сайтом, включая перенаправление HTTPS, за исключением ожидаемых перенаправлений 404, которые не выполняются для URL-адресов, начинающихся со знака вопроса. Как это исправить?

Вот моя конфигурация:

server {
    server_name example.com;
    root /var/www/example.com;
    index index.html;
    listen 443;
    ssl on;      
    ...

    rewrite "/?format=feed&type=rss" https://example.com/rss.xml permanent;

    location ~* \.(?:ico|css|js|gif|jpeg|jpg|png|txt|svg|eot|woff|ttf)$ {
            expires max;
            add_header Pragma public;
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
            add_header Access-Control-Allow-Origin *;
            valid_referers none blocked example.com;
            if ($invalid_referer) {
                    return 403;
            }
    }
}

# HTTP --> HTTPS
server {
        listen 80;
        server_name www.example.com example.com;
        return 301 https://example.com$request_uri;
}

Знак вопроса означает конец части пути в uri и начало строки запроса. Следовательно, почему nginx не возвращает 404 на основе части после вопросительного знака; запрошенный ресурс действительно существует, и ему просто передаются параметры строки запроса.

Что касается другой части вопроса, я считаю, что оператор rewrite nginx на самом деле не соответствует части строки запроса uri.

Однако вы должны иметь возможность делать что-то вроде:

if ($args ~ "format=feed&type=rss") {
    rewrite ^ https://example.com/rss.xml? permanent;
}

NGinx интерпретирует все, что следует за ? как строка запроса, а не как путь.

Он вернет только 404 для несуществующего пути, но не для строки запроса.

например:

  • example.com/123 : если путь /123 существует, и если для этого пути есть индексный файл, тогда все в порядке, иначе он вернет 404

  • example.com/?123 : если в корневом каталоге есть индексный файл для example.com тогда ладно. Он не проверяет, ?123 существует, поскольку он рассматривает это не как путь, а как строку запроса.