Como posso ter a mesma regra para dois locais na configuração do NGINX?

153

Como posso ter a mesma regra para dois locais na configuração do NGINX?

Eu tentei o seguinte

server {
  location /first/location/ | /second/location/ {
  ..
  ..
  }
}

mas o nginx reload lançou este erro:

nginx: [emerg] invalid number of arguments in "location" directive**
user1661010
fonte

Respostas:

239

Experimentar

location ~ ^/(first/location|second/location)/ {
  ...
}

Os ~meios para usar uma expressão regular para o URL. Os ^meios para verificar a partir do primeiro caractere. Isso procurará um /seguido por um dos locais e depois por outro /.

curtwphillips
fonte
37
OBSERVAÇÃO: se isso ocorrer com frequência (como milhares), haverá uma penalidade de desempenho devido à correspondência de expressões regulares. Além disso, a ordem de correspondência é substancialmente diferente. Em muitos casos "pequenos", ele se comportará como você deseja, mas isso é algo para se manter ciente. Pessoalmente, quero que o "local" do Nginx suporte várias condições "=" em vez de depender de uma regra de regex.
Bernard
7
IMHO, isso deve ser mais eficiente: location ~ (patternOne | patternTwo) {...}
stamster 17/01/17
2
Esta solução não funcionou para mim; no entanto, o comentário de @ stamster fez; Estou executandonginx/1.13.2
TJ Biddle
1
se você precisar proxy_passtrabalhar, consulte esta resposta: stackoverflow.com/a/46625656/1246870
avs099
1
Isso não funciona para mim extremidades URL quando originais com nenhuma barra
The Godfather
88

Outra opção é repetir as regras em dois locais de prefixo usando um arquivo incluído. Como os locais de prefixo são independentes da posição na configuração, usá-los pode economizar alguma confusão, à medida que você adiciona outros locais de regex posteriormente. Evitar locais regex, quando possível, ajudará sua configuração a ser dimensionada sem problemas.

server {
    location /first/location/ {
        include shared.conf;
    }
    location /second/location/ {
        include shared.conf;
    }
}

Aqui está uma amostra shared.conf:

default_type text/plain;
return 200 "http_user_agent:    $http_user_agent
remote_addr:    $remote_addr
remote_port:    $remote_port
scheme:     $scheme
nginx_version:  $nginx_version
";
Cole Tierney
fonte
você pode adicionar shared.confexemplo e localização?
Дмитрий Кулешов
5
Adicionei um exemplo de arquivo shared.conf. Você pode usar um caminho absoluto para o shared.conf ou colocá-lo no diretório nginx. Nesse caso, ele contém apenas algumas diretivas.
Cole Tierney
40

O regex e os arquivos incluídos são bons métodos, e eu os uso com frequência. Mas outra alternativa é usar um "local nomeado", que é uma abordagem útil em muitas situações - especialmente as mais complicadas. A página oficial "If is Evil" mostra essencialmente o seguinte como uma boa maneira de fazer as coisas:

error_page 418 = @common_location;
location /first/location/ {
    return 418;
}
location /second/location/ {
    return 418;
}
location @common_location {
    # The common configuration...
}

Existem vantagens e desvantagens nessas várias abordagens. Uma grande vantagem de uma regex é que você pode capturar partes da correspondência e usá-las para modificar a resposta. Obviamente, você geralmente pode obter resultados semelhantes com as outras abordagens, definindo uma variável no bloco original ou usando map. A desvantagem da abordagem regex é que ela pode ficar pesada se você deseja combinar uma variedade de locais, além da baixa precedência de uma regex simplesmente não se encaixar na maneira como você deseja combinar locais - sem mencionar que aparentemente há impactos no desempenho de regexes em alguns casos.

A principal vantagem de incluir arquivos (até onde eu sei) é que ele é um pouco mais flexível sobre exatamente o que você pode incluir - não precisa ser um bloco de localização completo, por exemplo. Mas também é subjetivamente um pouco mais desajeitado do que locais nomeados.

Observe também que há uma solução relacionada que você pode usar em situações semelhantes: locais aninhados. A idéia é que você comece com um local muito geral, aplique alguma configuração comum a várias das correspondências possíveis e, em seguida, tenha locais aninhados separados para os diferentes tipos de caminhos que deseja corresponder. Por exemplo, pode ser útil fazer algo assim:

location /specialpages/ {
    # some config
    location /specialpages/static/ {
        try_files $uri $uri/ =404;
    }
    location /specialpages/dynamic/ {
        proxy_pass http://127.0.0.1;
    }
}
Mike
fonte
7

Essa é uma abordagem curta, porém eficiente e comprovada:

location ~ (patternOne|patternTwo){ #rules etc. }

Assim, pode-se facilmente ter vários padrões com sintaxe de canal simples apontando para as mesmas regras / bloco de localização.

stamster
fonte