Comment puis-je avoir la même règle pour deux emplacements dans la configuration NGINX?

153

Comment puis-je avoir la même règle pour deux emplacements dans la configuration NGINX?

J'ai essayé ce qui suit

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

mais nginx reload a jeté cette erreur:

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

Réponses:

240

Essayer

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

Les ~moyens d'utiliser une expression régulière pour l'url. Les ^moyens de vérifier à partir du premier caractère. Cela recherchera un /suivi de l'un des emplacements, puis d'un autre /.

Curtwphillips
la source
37
REMARQUE: si cela se produit souvent (comme des milliers), cela entraînera une pénalité de performances en raison de la correspondance regex. De plus, l'ordre d'appariement est sensiblement différent. Dans beaucoup de "petits" cas, il se comportera comme vous le souhaitez, mais il faut rester conscient de cela. Je souhaite personnellement que Nginx "location" prenne en charge plusieurs conditions "=" au lieu de s'appuyer sur une règle regex.
Bernard
7
IMHO, cela devrait être plus efficace: location ~ (patternOne | patternTwo) {...}
stamster
2
Cette solution n'a pas fonctionné pour moi; cependant le commentaire de @ stamster l'a fait; Je coursnginx/1.13.2
TJ Biddle
1
si vous avez besoin proxy_passde travailler, consultez cette réponse: stackoverflow.com/a/46625656/1246870
avs099
1
Cela ne fonctionne pas pour moi lorsque l'URL d'origine se termine sans barre oblique
The Godfather
88

Une autre option consiste à répéter les règles dans deux emplacements de préfixe à l'aide d'un fichier inclus. Étant donné que les emplacements de préfixe sont indépendants de la position dans la configuration, leur utilisation peut éviter une certaine confusion lorsque vous ajoutez d'autres emplacements de regex plus tard. Éviter les emplacements de regex lorsque vous le pouvez aidera votre configuration à évoluer en douceur.

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

Voici un exemple 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
la source
pouvez-vous ajouter s'il vous plaît un shared.confexemple et un emplacement?
Дмитрий Кулешов
5
J'ai ajouté un exemple de fichier shared.conf. Vous pouvez utiliser un chemin absolu vers le shared.conf ou le mettre dans votre répertoire nginx. Dans ce cas, il ne contient que quelques directives.
Cole Tierney
40

Les regex et les fichiers inclus sont de bonnes méthodes, et je les utilise fréquemment. Mais une autre alternative consiste à utiliser un «emplacement nommé», qui est une approche utile dans de nombreuses situations, en particulier les plus compliquées. La page officielle "If is Evil" montre essentiellement ce qui suit comme un bon moyen de faire les choses:

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

Ces différentes approches présentent des avantages et des inconvénients. Un gros avantage d'une expression régulière est que vous pouvez capturer des parties de la correspondance et les utiliser pour modifier la réponse. Bien sûr, vous pouvez généralement obtenir des résultats similaires avec les autres approches en définissant une variable dans le bloc d'origine ou en utilisant map. L'inconvénient de l'approche regex est qu'elle peut devenir compliquée si vous souhaitez faire correspondre une variété d'emplacements, et la faible priorité d'une expression régulière peut tout simplement ne pas correspondre à la façon dont vous souhaitez faire correspondre les emplacements - sans oublier qu'il y a apparemment des impacts sur les performances. des regexes dans certains cas.

Le principal avantage de l'inclusion de fichiers (pour autant que je sache) est qu'il est un peu plus flexible sur ce que vous pouvez inclure exactement - il n'est pas nécessaire qu'il s'agisse d'un bloc d'emplacement complet, par exemple. Mais c'est aussi subjectivement un peu plus maladroit que les emplacements nommés.

Notez également qu'il existe une solution connexe que vous pourrez peut-être utiliser dans des situations similaires: les emplacements imbriqués. L'idée est de commencer par un emplacement très général, d'appliquer une configuration commune à plusieurs des correspondances possibles, puis d'avoir des emplacements imbriqués distincts pour les différents types de chemins que vous souhaitez faire correspondre. Par exemple, il peut être utile de faire quelque chose comme ceci:

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

C'est une approche courte, mais efficace et éprouvée:

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

Ainsi, on peut facilement avoir plusieurs modèles avec une syntaxe de tuyau simple pointant vers le même bloc / règles de localisation.

stamster
la source