Несколько условий для перезаписи Nginx

Я пытаюсь найти лучший способ переписать это правило, чтобы оно работало на nginx:

   RewriteCond %{REQUEST_URI} !^/clip-art/.*$
   RewriteCond %{REQUEST_URI} !^/Clip-Art/.*$
   RewriteCond %{REQUEST_URI} !^/cgi-bin/.*$
   RewriteCond %{REQUEST_URI} !^/images/.*$
   RewriteCond %{REQUEST_URI} !/invitation/
   RewriteCond %{REQUEST_URI} !/designer/
   RewriteRule ^/(.*)/(.*)/(.*)/(.*)$ /clip-art/$1/$2/$3/$4 [r=301,nc,l]

Я знаю, что могу сделать что-то вроде:

   if ($request_uri !~ "/designer") {
       rewrite ^/(.*)/(.*)/(.*)/(.*)$ /clip-art/$1/$2/$3/$4 permanent;
   }

Но очевидно, что это работает только с одним из имен папок. Как мне заставить его работать с несколькими именами папок?

2 ответа

Решение

Регулярные выражения относительно неэффективны и, как правило, не приветствуются в конфигурациях Nginx, когда других методов будет достаточно. Здесь есть несколько случаев, которые не требуют регулярных выражений:

location /clip-art/ {
    # ...
}

location /Clip-Art/ {
    # ...
}

location /images/ {
    # ...
}

location /cgi-bin/ {
    # ...
}

Если вы просто обслуживаете статические изображения хотя бы из трех из них, мы можем сделать это еще проще. ^~ Префикс означает, что эти правила будут иметь приоритет над правилами на основе регулярных выражений, которые в противном случае имели бы приоритет. Хотя это имеет много применений, оно может выступать в качестве функции безопасности при работе с каталогами, содержащими только статические ресурсы. Если кому-то удастся загрузить файл PHP или какой-либо другой исполняемый код, который обычно обрабатывается местоположением регулярного выражения, местоположение перед регулярным выражением (с ^~), и файл не будет выполнен. Я также опустил типичный $uri/ потому что это не совсем применимо к статическим каталогам ресурсов.

location ^~ /clip-art/ { try_files $uri =404; }
location ^~ /Clip-Art/ { try_files $uri =404; }
location ^~ /images/   { try_files $uri =404; }

location /cgi-bin/ {
    # ...
}

Что касается остальных условий, Nginx спроектирован так, чтобы соответствовать, начиная с начала каждого URI. В идеале вы можете обрабатывать подобные сценарии в своем приложении, а не в Nginx. Однако в этом конкретном случае относительно эффективное регулярное выражение может быть написано:

rewrite "^((?:/(?!designer|invitation)[^/]+){4})/?$" /clip-art$1 permanent;

https://stackoverflow.com/questions/406230/regular-expression-to-match-a-line-that-doesnt-contain-a-word содержит пример использования регулярных выражений для поиска строк, которые не содержат определенных слов.

Используйте этот подход регулярных выражений в вашем location директива, а затем использовать ваш rewrite заявление внутри location блок.

Кроме того, я предлагаю вам использовать .+ (одно или несколько совпадений) вместо .* (ноль или более совпадений) в качестве символа подстановки в rewrite директивы.

Другие вопросы по тегам