Multiple RewriteConditions: How to chain them before a set of rules?

前端 未结 3 1868
梦如初夏
梦如初夏 2020-12-14 07:50

Q1: How to chain these two conditions making them if BOTH A AND B, then proceed...
Q2: How to make them stick for

相关标签:
3条回答
  • 2020-12-14 08:13

    Q1: The default is AND.

    Q2: They will only affect the RewriteRule immediately below.

    0 讨论(0)
  • 2020-12-14 08:15

    You can't do it that way. You have to either repeat your RewriteConds or rethink your rewrite rule using references to do it all in one rule. The first route, though not pretty, would be the easiest. so

    RewriteCond A
    RewriteCond B
    RewriteRule 1
    
    RewriteCond A #duplicate
    RewriteCond B #duplicate
    RewriteRule 2
    
    0 讨论(0)
  • 2020-12-14 08:20

    Here are some tricks for making a RewriteCond stack apply to multiple RewriteRule's, sorted by increasing WTF's per minute. But this is configuration and not code, so those rules don't apply, right? :-)

    1. Environment variable

    When you have many RewriteCond's, storing their result in an environment variable and then testing against in every rule is more 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. Skip flag

    This one's a bit subtle. Using the [S] or [skip] flag you can cause your entire block of RewriteRule's to be skipped.

    # 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
    

    This acts sort of like an if-statement with the RewriteCond's being the condition and RewriteRule's being the code block.

    You get less duplication, but the tradeoff is the code is less clear, and you have to update [skip=N] every time you add or remove a rule from this set of N RewriteRule's.

    <fun>

    All right, if you're still reading, here you'll find two more solutions where the WTF's per minute reach and exceed a critical point. They're for amusement only, and you'll see why.

    3. Skip flag without N

    Yes, there is a way to use the [skip] flag without including N, the number of RewriteRule's you want to apply the RewriteCond stack to. That is... if you include a pair of RewriteCond's before each RewriteRule, and oh yeah, one more at the end.

    # 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
    

    The trick here is that every [skip=1] rule gets processed if and only if the RewriteCond's succeeded, and every [skip=2] rule gets processed if and only if they failed.

    4. URL marker

    Use part of the URL to hold state then match against it in your RewriteRule's.

    # 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
    

    The new URL with the marker is invalid, but the last RewriteRule revert it, right? Well, only if it gets processed, so don't let the marker URL escape this round of mod_rewrite processing before it gets reverted. You'll get a 404 then.

    0 讨论(0)
提交回复
热议问题