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

Nginx: доступ к одному и тому же контенту с нескольких URL-адресов

Я пытаюсь настроить nginx так, чтобы к одному и тому же статическому контенту можно было получить доступ через два разных URL-адреса без любые перенаправления.

Например, если клиент входит /path/to/A в их браузере, я хочу получить тот же контент, что и /path/to/B.

Я пробовал использовать rewrite, но в этом случае Nginx дает мне 301 редирект.

Например:

server {
    root /my/www/data;

    rewrite ^/path/to/A(.*)$ /path/to/B$1;
    # Note: /my/www/data/path/to/B *does* actually exist on disk.
    # However, the .../A version does not.
}

Я думаю, один из способов сделать это - использовать символическую ссылку /my/www/data/A указать на /my/www/data/B, но я пытаюсь сделать это, используя конфигурацию сервера, а не трюки с файловой системой.

Мои вопросы:

  1. Как это может быть сделано?
  2. При каких обстоятельствах rewrite модуль выполняет внутреннее перенаправление вместо отправки 30-кратного кода клиенту? Я не могу ясно сказать из документов.

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

РЕДАКТИРОВАТЬ: Вот настоящий конфиг, с curl команды и т. д .:

Во-первых, конфиг:

server {

    root /usr/share/nginx/www/mydata;
    index index.html index.htm;

    # Make site accessible from http://localhost/
    server_name localhost;

    location / {
        try_files $uri $uri/ =404;
    }

    rewrite_log on;    
    rewrite ^/A(.*)$ /B$1 last;
}

Теперь содержимое моего корневого веб-сайта:

$ find /usr/share/nginx/www/mydata/
/usr/share/nginx/www/mydata/
/usr/share/nginx/www/mydata/B
/usr/share/nginx/www/mydata/B/index.html
/usr/share/nginx/www/mydata/index.html

И с этим бегом вот что я получаю curl:

$ curl -i 'http://localhost/A'
HTTP/1.1 301 Moved Permanently
Server: nginx/1.2.1
...
Location: http://localhost/B/
...
<snipped>

Однако отмечу, что /A/ (с косой чертой в конце) и /A/index.html работать нормально:

$ curl -i 'http://localhost/A/'
HTTP/1.1 200 OK
Server: nginx/1.2.1
<snip - I see data for B/index.html, as I expect>

(Те же результаты для /A/index.html).

Так что только в первом случае я получаю редирект 301, хотя в моей конфигурации это никогда не упоминается явно.

В чем дело?

Это стандартное поведение веб-серверов, отображающих индексы каталогов, например, Apache делает то же самое. Всякий раз, когда вы запрашиваете просто «каталог», он перенаправляет вас в «каталог /» вот так.

Документация Apache явно об этом говорит, например https://httpd.apache.org/docs/2.4/mod/mod_dir.html говорит

Редирект "завершающая косая черта" выдается, когда сервер получает запрос на URL. http: // имя сервера / foo / имя каталога где dirname - это каталог. Для каталогов требуется косая черта в конце, поэтому mod_dir перенаправляет на http: // имя сервера / foo / имя каталога /.

Похоже, что документация nginx немного более скромна, например http://nginx.org/en/docs/http/ngx_http_autoindex_module.html просто говорит:

Модуль ngx_http_autoindex_module обрабатывает запросы, заканчивающиеся символом косой черты (‘/’), и выдает список каталогов. Обычно запрос передается модулю ngx_http_autoindex_module, когда модуль ngx_http_index_module не может найти индексный файл.

Он не объясняет предыдущий шаг, как запрос заканчивается косой чертой, что кажется неявным.

В сети есть еще один старый вопрос по той же проблеме: https://stackoverflow.com/questions/15555428/nginx-causes-301-redirect-if-theres-no-trailing-slash

rewrite в nginx не приводит к статусу 301 в целом (если явно не настроен), поэтому 301, вероятно, вызван другими частями вашего nginx config.

rewrite это правильный способ достичь того, чего вы хотите, ваш подход верен.

Хорошо, после некоторых экспериментов я нашел несколько разных решений.

Напомним, я хочу /A оставаться как /A в браузере пользователя (без перенаправления на /B), но я все же хочу, чтобы он отображал контент из /B.

Опция 1: Используйте символическую ссылку (: это работает, но вам нужен доступ к файловой системе. Решает проблему.

Вариант 2: Предотвратить автоматическое перенаправление 301 после косой черты с помощью точного совпадения (=) блок местоположения:

location = /A {
    rewrite "" /B/;
}
# Note: the below should probably be inside a location block.
rewrite ^/A(.+)$ /B$1 last;

Я узнал об этом из Документы Nginx:

без завершающей косой черты постоянное перенаправление с кодом 301 будет возвращено на запрошенный URI с добавленной косой чертой. Если это нежелательно, можно определить точное соответствие URI и местоположения.

Вариант 3: Используйте перенаправление с /A к /A/, но делайте это вручную, чтобы он не возвращался клиенту в виде (переписанного) перенаправления на /B/:

location = /A {
    return 301 /A/;
}
location /A/ {
    rewrite ^/A/(.*)$ /B/$1 last;
}

В итоге я выбрал вариант 3, поскольку он делает /A вести себя так же, как /B, включая редирект с косой чертой (но теперь в нужное место).