Как я могу иметь одинаковое правило для двух мест в конфигурации NGINX?

153

Как я могу иметь одинаковое правило для двух мест в конфигурации NGINX?

Я пробовал следующее

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

но перезагрузка nginx выкинула эту ошибку:

nginx: [emerg] invalid number of arguments in "location" directive**
user1661010
источник

Ответы:

240

Пытаться

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

В ~средстве использовать регулярное выражение для URL. В ^средства для проверки с первого символа. Это будет искать /одно из следующих мест, а затем другое /.

curtwphillips
источник
37
ПРИМЕЧАНИЕ: если это происходит часто (например, тысячи), это повлечет за собой снижение производительности из-за соответствия регулярному выражению. Также порядок сопоставления существенно отличается. Во многих «маленьких» случаях он будет вести себя так, как вы хотите, но об этом нужно знать. Я лично хочу, чтобы Nginx "location" поддерживал несколько условий "=" вместо того, чтобы полагаться на правило регулярных выражений.
Бернард
7
ИМХО, это должно быть более эффективно: location ~ (patternOne | patternTwo) {...}
stamster
2
Это решение не сработало для меня; однако комментарий @ stamster сделал; Я бегуnginx/1.13.2
TJ Biddle
1
если вам нужно proxy_passработать, посмотрите этот ответ: stackoverflow.com/a/46625656/1246870
avs099
1
Это не работает для меня, когда оригинальный URL заканчивается без косой черты
Крестный отец
88

Другой вариант - повторить правила в двух местах префиксов, используя включенный файл. Поскольку местоположения префиксов в конфигурации не зависят от местоположения, их использование может сэкономить некоторую путаницу, поскольку вы добавите другие местоположения регулярных выражений позже. Избежание мест регулярных выражений, когда вы можете, поможет плавно масштабировать вашу конфигурацию.

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

Вот пример 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
";
Коул Тирни
источник
Можете ли вы добавить shared.confпример и пример?
Дмитрий Кулешов
5
Я добавил пример файла shared.conf. Вы можете использовать абсолютный путь к shared.conf или поместить его в каталог nginx. В этом случае он просто содержит пару директив.
Коул Тирни
40

И регулярные выражения, и включенные файлы - хорошие методы, и я часто использую их. Но другой альтернативой является использование «именованного местоположения», что является полезным подходом во многих ситуациях, особенно в более сложных. Официальный «Если это зло» страница показывает , по существу, следующие как хороший способ делать вещи:

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

У этих различных подходов есть свои преимущества и недостатки. Одним из больших преимуществ регулярного выражения является то, что вы можете захватывать части матча и использовать их для изменения ответа. Конечно, вы можете достичь аналогичных результатов с другими подходами, либо установив переменную в исходном блоке, либо используя map. Недостатком подхода регулярных выражений является то, что он может стать громоздким, если вы хотите сопоставлять различные местоположения, плюс низкий приоритет регулярного выражения может просто не соответствовать тому, как вы хотите сопоставлять местоположения - не говоря уже о том, что, очевидно, это влияет на производительность от регулярных выражений в некоторых случаях.

Основное преимущество включения файлов (насколько я могу судить) состоит в том, что он немного более гибок в отношении того, что именно вы можете включить - например, он не должен быть полным блоком местоположения. Но это также субъективно немного грубее, чем названные места.

Также обратите внимание, что есть связанное решение, которое вы можете использовать в подобных ситуациях: вложенные местоположения. Идея состоит в том, что вы должны начать с очень общего местоположения, применить некоторую конфигурацию, общую для нескольких возможных совпадений, а затем иметь отдельные вложенные местоположения для различных типов путей, которые вы хотите сопоставить. Например, может быть полезно сделать что-то вроде этого:

location /specialpages/ {
    # some config
    location /specialpages/static/ {
        try_files $uri $uri/ =404;
    }
    location /specialpages/dynamic/ {
        proxy_pass http://127.0.0.1;
    }
}
Майк
источник
7

Это короткий, но эффективный и проверенный подход:

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

Таким образом, можно легко иметь несколько шаблонов с простым синтаксисом канала, указывающих на один и тот же блок / правила расположения.

stamster
источник