Nginx - raiz versus alias, para servir arquivos únicos?

66

Depois de muitas horas nginxservindo arquivos únicos, como robots.txt(dica: limpe o cache do navegador toda vez), acabei com duas maneiras diferentes, uma usando a diretiva de alias e outra usando a diretiva de raiz , da seguinte maneira:

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

Existe alguma diferença funcional entre os dois? Ou questões de segurança? Algum conflito com outras diretrizes? (Ambos pareciam bem com outro local / estático). Ou algum motivo para escolher um sobre o outro?

Nota - Não usei os dois ao mesmo tempo :) Tentei cada um, um de cada vez, e ambos funcionaram. Não estou perguntando como os dois interagem juntos no mesmo arquivo, mas qual seria melhor usar.

Cyclops
fonte

Respostas:

71

Bem, essas duas diretivas são ligeiramente funcionais diferentes, porque você não usa a correspondência exata no último caso. Portanto, /robots.txt1111corresponderá também ao seu segundo local.
location =/robots.txt { root /home/www/static/; }é um equivalente funcional exato da sua primeira diretiva.

Alex
fonte
Bom ponto, obrigado. Mas você pode usar um =em ambos os casos, correto? Ou apenas se aplica a root? Além disso, veja minha edição - não pretendia usar os dois ao mesmo tempo. :)
Ciclope
@ Cyclops sim, você pode usar =nos dois casos.
Alexander Azarov
Então, eles seriam os mesmos - existe alguma razão para escolher uma diretiva em detrimento da outra? É a minha pergunta principal.
Ciclope
@ Cyclops Basicamente, não existe esse motivo.
97711 Alex
41

Sim, há uma diferença: com "alias", você pode ... bem, alias para outro nome de arquivo, como

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

enquanto que

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

força você a nomear seu arquivo no servidor e também robots.txt. Eu uso a primeira opção, pois gosto de nomear meus arquivos de robôs no meu servidor como tld.domain.subdomain-robots.txt; por exemplo

location /robots.txt { alias /home/www/static/ch.notex.static-robots.txt; }
Hasan Karahan
fonte
1

Eu acho que vale a pena explicar explicitamente que o nginx está operando em prefixos e não em arquivos por si só. No primeiro caso,

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

O nginx substitui o prefixo da string /robots.txtno caminho da URL /home/www/static/robots.txte depois usa o resultado como um caminho do sistema de arquivos. Representado como pseudocódigo, isso seria algo como:

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

Assim, /robots.txté veiculado /home/www/static/robots.txtporque /robots.txto /robots.txtprefixo despojado é a sequência vazia e anexa a sequência vazia para /home/www/static/robots.txtdeixá-la inalterada. Mas, /robots.txt1seria servido de /home/www/static/robots.txt1e /robots.txt/foobarseria servido de /home/www/static/robots.txt/foobar. Esses arquivos podem não existir, fazendo com que o nginx envie uma resposta 404, e provavelmente robots.txtnão é um diretório, mas o nginx não sabe disso com antecedência, e tudo isso é baseado em prefixos de string e não no que parece ser um arquivo ou diretório pela ausência ou presença de uma barra final.

Considerando que, no segundo caso,

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

O nginx insere a sequência /home/www/static/no início do caminho da URL e, em seguida, usa o resultado como um caminho do sistema de arquivos. No pseudocódigo, isso seria algo como:

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

Isso tem exatamente o mesmo resultado que o primeiro caso, mas por um motivo diferente. Não há remoção de prefixo, mas como todo caminho de URI deve conter o prefixo /robots.txt, os caminhos do sistema de arquivos sempre começarão com o /home/www/static//robots.txtque é equivalente /home/www/static/robots.txt .

Obviamente, o pseudocódigo não conta a história toda, como, por exemplo, o nginx não usa cegamente caminhos de URL brutos como /../../../etc/passwd, a try_filesdiretiva altera o comportamento de root/ aliase há restrições sobre onde aliaspode ser usado.

kbolino
fonte
0

Há uma diferença, quando o alias é para um diretório inteiro.

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

vai funcionar, enquanto

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

não vai fazer. Isso teria que ser

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

(Fácil de confundir)

BurninLeo
fonte