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