Несколько RewriteConditions: как их связать перед набором правил? - PullRequest
23 голосов
/ 15 марта 2011

Q1 : Как связать эти два условия, делая их if BOTH A AND B, then proceed...
Q2 : Как заставить их придерживаться всех приведенных ниже правил переписывания, а не только первого правила?

RewriteCond %{REQUEST_URI} ^IMAGE-.*$      // if filename starts with IMG- and,
RewriteCond %{REQUEST_FILENAME} !-f        // if file does exist, then proceed:
RewriteRule Rule1
RewriteRule Rule2
RewriteRule Rule3

# -- END IF -- STOP HERE -- #

Ответы [ 3 ]

36 голосов
/ 18 июня 2014

Вот несколько приемов для применения стека RewriteCond к нескольким RewriteRule, отсортированным по возрастанию WTF в минуту . Но это конфигурация, а не код, поэтому эти правила не применяются, верно? : -)

1. Переменная окружения

Когда у вас много RewriteCond, их результаты сохраняются в переменной окружения, а затем проверяются в каждом правиле более компактно.

# Your RewriteCond stack.
RewriteCond %{REQUEST_URI} !^IMAGE-.*$ [OR]
RewriteCond %{REQUEST_FILENAME} -f
# Store environment variable.
RewriteRule ^ - [E=TRUE:YEP]
# Assert environment variable in remaining RewriteRule's.
RewriteCond %{ENV:TRUE} =YEP
RewriteRule Rule1
RewriteCond %{ENV:TRUE} =YEP
RewriteRule Rule2
RewriteCond %{ENV:TRUE} =YEP
RewriteRule Rule3

2. Пропустить флаг

Это немного неуловимо. Используя флаг [S] или [skip], вы можете пропустить весь блок из RewriteRule.

# Your RewriteCond stack.
RewriteCond %{REQUEST_URI} !^IMAGE-.*$ [OR]
RewriteCond %{REQUEST_FILENAME} -f
# If RewriteCond's match, skip the next RewriteRule.
RewriteRule ^ - [skip=1]
# Otherwise, this rule will match and the rest will be skipped.
RewriteRule ^ - [skip=3]
RewriteRule Rule1
RewriteRule Rule2
RewriteRule Rule3

Это действует как оператор if, где RewriteCond является условием, а RewriteRule является блоком кода.

Вы получаете меньше дублирования, но компромисс в том, что код менее понятен, и вы должны обновлять [skip=N] каждый раз, когда добавляете или удаляете правило из этого набора N RewriteRule. .

Хорошо, если вы все еще читаете, здесь вы найдете еще два решения, где WTF в минуту достигают и превышают критическую точку. Они только для развлечения, и вы поймете, почему.

3. Пропустить флаг без N

Да, есть способ использовать флаг [skip] без включения N , числа RewriteRule, к которому вы хотите применить стек RewriteCond. То есть ... если вы включите пару RewriteCond перед каждым RewriteRule, и, о да, еще один в конце.

# Your RewriteCond stack.
RewriteCond %{REQUEST_URI} !^IMAGE-.*$ [OR]
RewriteCond %{REQUEST_FILENAME} -f
# If RewriteCond's match, skip the next RewriteRule.
RewriteRule ^ - [skip=1]  # succeeded
RewriteRule ^ - [skip=2]  # failed
RewriteRule Rule1
RewriteRule ^ - [skip=1]  # succeeded
RewriteRule ^ - [skip=2]  # failed
RewriteRule Rule2
RewriteRule ^ - [skip=1]  # succeeded
RewriteRule ^ - [skip=2]  # failed
RewriteRule Rule3
RewriteRule ^ -           # no-op to cover for last [skip=2] rule

Хитрость в том, что каждое правило [skip=1] обрабатывается тогда и только тогда, когда RewriteCond выполнено успешно, а каждое правило [skip=2] обрабатывается тогда и только тогда, когда оно не выполнено.

4. Маркер URL

Используйте часть URL для удержания состояния, а затем сопоставьте его с вашими RewriteRule.

# Your RewriteCond stack.
RewriteCond %{REQUEST_URI} !^IMAGE-.*$ [OR]
RewriteCond %{REQUEST_FILENAME} -f
# If RewriteCond's match, prepend bogus marker "M#" to internal URL.
RewriteRule .* M#$0
# All your RewriteRule's test for this marker plus whatever else.
RewriteRule ^M#.*Rule1
RewriteRule ^M#.*Rule2
RewriteRule ^M#.*Rule3
# Finally, don't forget to strip off the bogus marker.
RewriteRule ^M#(.*) $1

Новый URL с маркером недействителен, но последний RewriteRule вернул его, верно? Ну, только если он будет обработан, так что не позволяйте URL-адресу маркера избежать этого раунда обработки mod_rewrite до того, как он будет возвращен. Тогда вы получите 404.

20 голосов
/ 15 марта 2011

Q1: по умолчанию используется AND.

Q2: они влияют только на RewriteRule, который находится ниже.

16 голосов
/ 15 марта 2011

Вы не можете сделать это таким образом.Вы должны либо повторить ваши RewriteConds, либо переосмыслить правило перезаписи, используя ссылки, чтобы сделать все это в одном правиле.Первый маршрут, хотя и не красивый, будет самым простым.так что

RewriteCond A
RewriteCond B
RewriteRule 1

RewriteCond A #duplicate
RewriteCond B #duplicate
RewriteRule 2
...