web-dev-qa-db-fra.com

RewriteConditions multiples: comment les enchaîner avant un ensemble de règles?

Q1: Comment enchaîner ces deux conditions en les rendant if BOTH A AND B, then proceed...
Q2: Comment les faire coller à toutes les règles de réécriture ci-dessous et pas seulement à la première règle?

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 -- #
24
Sam

Voici quelques astuces pour appliquer une pile RewriteCond à plusieurs RewriteRule, triées en augmentant WTF par minute . Mais c'est de la configuration et non du code, donc ces règles ne s'appliquent pas, non? :-)

1. Variable d'environnement

Lorsque vous avez plusieurs RewriteCond, le stockage de leur résultat dans une variable d'environnement, puis les tests dans chaque règle est plus compact.

# 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. Ignorer le drapeau

Celui-ci est un peu subtil. En utilisant le [S] ou [skip] flag vous pouvez faire sauter votre bloc entier de 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

Cela agit en quelque sorte comme une instruction if avec RewriteCond comme condition et RewriteRule comme bloc de code.

Vous obtenez moins de duplication, mais le compromis est que le code est moins clair et vous devez mettre à jour [skip=N] chaque fois que vous ajoutez ou supprimez une règle de cet ensemble de [~ # ~] n [~ # ~] RewriteRule.

<fun>

D'accord, si vous lisez toujours, vous trouverez ici deux autres solutions où les WTF par minute atteignent et dépassent un point critique. Ils ne sont que pour le plaisir et vous comprendrez pourquoi.

3. Ignorer le drapeau sans N

Oui, il existe un moyen d'utiliser le [skip] flag sans inclure [~ # ~] n [~ # ~] , le nombre de RewriteRule que vous souhaitez appliquer RewriteCond pile vers. C'est-à-dire ... si vous incluez une paire de RewriteCond avant chaque RewriteRule, et oh oui, une de plus à la fin.

# 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

L'astuce ici est que chaque [skip=1] la règle est traitée si et seulement si le RewriteCond a réussi, et chaque [skip=2] la règle est traitée si et seulement si elle a échoué.

4. Marqueur d'URL

Utilisez une partie de l'URL pour conserver l'état, puis comparez-le dans vos 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

La nouvelle URL avec le marqueur n'est pas valide, mais la dernière RewriteRule la rétablit, non? Eh bien, seulement s'il est traité, alors ne laissez pas l'URL du marqueur échapper à ce cycle de traitement mod_rewrite avant qu'elle ne soit annulée. Vous obtiendrez alors un 404.

40
mxxk

Q1: La valeur par défaut est AND.

Q2: Ils n'affecteront que la règle de réécriture immédiatement ci-dessous.

22
Clodoaldo Neto

Vous ne pouvez pas le faire de cette façon. Vous devez soit répéter vos RewriteConds, soit repenser votre règle de réécriture en utilisant des références pour tout faire dans une seule règle. La première route, bien que pas jolie, serait la plus simple. alors

RewriteCond A
RewriteCond B
RewriteRule 1

RewriteCond A #duplicate
RewriteCond B #duplicate
RewriteRule 2
16
XP84