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

Nginx - корень или псевдоним для обслуживания отдельных файлов?

После многих часов получения nginx для обслуживания отдельных файлов, таких как robots.txt (подсказка: очистите кеш вашего браузера каждый раз), у меня было два разных способа, один из которых псевдоним директива, и одна с использованием корень директива, например:

location /robots.txt { alias /home/www/static/robots.txt; }
location /robots.txt { root /home/www/static/;  }

Есть ли функциональный разница между двумя? Или проблемы с безопасностью? Есть конфликты с другими директивами? (Оба выглядели нормально с другим / статическим местоположением). Или есть причина предпочесть одно другому?

Примечание - я не использовал оба в то же время :) Скорее я пробовал каждый, по одному, и оба работали. Я не спрашиваю, как они оба взаимодействуют вместе в одном файле, но какой из них лучше использовать.

Что ж, эти две директивы немного различаются по функциональности, потому что в последнем случае вы не используете точное соответствие. Так, /robots.txt1111 будет соответствовать и вашему второму местоположению.
location =/robots.txt { root /home/www/static/; } является точным функциональным эквивалентом вашей первой директивы.

Да, есть разница: с "псевдонимом" вы можете .. ну, псевдоним для другого имени файла, например

location /robots.txt { alias /home/www/static/any-filename.txt; }

в то время как

location /robots.txt { root /home/www/static/; }

вынуждает вас назвать ваш файл на сервере также robots.txt. Я использую первый вариант, поскольку мне нравится называть файлы роботов на моем сервере tld.domain.subdomain-robots.txt; например

location /robots.txt { alias /home/www/static/ch.notex.static-robots.txt; }

Думаю, стоит прямо указать, что nginx работает с префиксами, а не с файлами как таковыми. В первом случае

location /robots.txt { alias /home/www/static/robots.txt; }

nginx заменяет строку префикс /robots.txt в пути URL с /home/www/static/robots.txt а затем использует результат как путь к файловой системе. Представленный как псевдокод, это будет примерно так:

if urlPath.startsWith("/robots.txt") {
    fsPath := "/home/www/static/robots.txt" + urlPath.stripPrefix("/robots.txt")
    serveFile(fsPath)
}

Так /robots.txt подается из /home/www/static/robots.txt так как /robots.txt лишенный /robots.txt префикс - это пустая строка, и добавление пустой строки к /home/www/static/robots.txt оставляет его без изменений. Но, /robots.txt1 будет обслуживаться из /home/www/static/robots.txt1 и /robots.txt/foobar будет обслуживаться из /home/www/static/robots.txt/foobar. Эти файлы могут не существовать, в результате чего nginx отправляет ответ 404, и вполне вероятно, что robots.txt в любом случае не является каталогом, но nginx не знает этого заранее, и все это основано на строковых префиксах, а не на том, что появляется быть файлом или каталогом по отсутствию или наличию завершающей косой черты.

А во втором случае

location /robots.txt { root /home/www/static/; }

nginx вставляет строку /home/www/static/ в начале пути URL, а затем использует результат как путь к файловой системе. В псевдокоде это будет примерно так:

if urlPath.startsWith("/robots.txt") {
    fsPath := "/home/www/static/" + urlPath
    serveFile(fsPath)
}

Результат такой же, как и в первом случае, но по другой причине. Здесь нет префикса, но поскольку каждый путь URI должен содержать префикс /robots.txt, то пути к файловой системе всегда будут начинаться с /home/www/static//robots.txt который эквивалентно /home/www/static/robots.txt.

Конечно, псевдокод не совсем раскрывает всю историю, например, nginx не будет слепо использовать необработанные URL-адреса, такие как /../../../etc/passwd, то try_files директива изменяет поведение root/alias, и есть ограничения на то, где alias может быть использован.

Есть разница, когда псевдоним предназначен для всего каталога.

    location ^~ /data/ { alias /home/www/static/data/; }

будет работать, пока

    location ^~ /data/ { root /home/www/static/data/; }

не пойдет. Это должно быть

    location ^~ /data/ { root /home/www/static/; }

(Легко запутать)