What is the precedence of multiple mod_rewrite rules in multiple .htaccess files? [closed]

↘锁芯ラ 提交于 2019-12-05 22:32:25

问题


I understand that the [L] following a rewrite rule means that it's the "last" but I'm not clear what the scope is

For example, when there are multiple .htaccess files, some with [L], which ones will apply?

Example:

root.com/subdirectory1/subdirectory2

  ^           ^            ^      
  |           |            |
  A           B            C

If there is an .htaccess file in each directory...

  1. In what order will they apply?
  2. If they contradict each other which takes precedence?
  3. Do they apply in serial? Are the results of the first passed to the next?
  4. Will matches in an earlier (or the same) file that RESULT from a later rule get applied?
  5. If there is an [L] in an earlier file will other files get considered?

回答1:


The [L] flag does indeed mean "last", but it only applies to the rules in the current scope. From your question, it only applies to the rules in the htaccess file. If there are rules in a subdirectory, any rules in the parent directory are thrown out the window. They are not applied at all, unless you use the RewriteOptions Inherit directive (which will append to the end of the rules any rules from the parent htaccess file).

Given your example:

root.com/subdirectory1/subdirectory2
  ^           ^            ^      
  |           |            |
  A           B            C

If there are htaccess files in A, B, and C, and rewrite rules in all 3, if one requests http://root.com (your "root.com" directory), only the rules in A get applied. If someone requests http://root.com/subdirectory1, then only the rules in B get applied, and any rules in A are ignored (without the Inherit option). Likewise, if someone goes to http://root.com/subdirectory1/subdirectory2, then only the rules in C get applied, if there are no inheriting options.

The [L] flag has no play in any of this, as the scope here is only within the rules of an htaccess file. Also note that [L] doesn't necessarily mean "stop rewriting HERE", as the rewrite engine will loop until the URI going into the engine stops changing. The [L] just means to stop rewriting in the current iteration of the rewrite engine's looping.


A bit more detail on the looping stuff:

During the URL processing pipeline, apache attempts to map a URL to a file or resource. Lots of different modules have a part to play in the processing pipeline, like mod_rewrite or mod_proxy or mod_alias. At any point, this URI can change, be flagged to be redirected, be flagged to be proxied, be flagged to throw an error, etc. When the URI gets to mod_rewrite, the rewrite engine collects a bunch of rules from the vhost config and the appropriate htaccess file; note, 2 different scopes here. Each scope of rules are applied to the URI and if none of the rules match, then mod_rewrite is done. If one of the rules match, there is an internal redirect, meaning the URI is changed and then redirected back to the processing pipeline and mod_rewrite. Thus the same scope of rules get applied again, and if one of the rules match and gets applied, the same thing happens again the the rules loop again. There's a directive that you can set in the vhost/server config called LimitInternalRecursion which sets the limit of these internal redirects. If the number of times the rewrite engine loops (i.e. redirects back to itself) exceeds this limit (which by default is 10, I think), then you get a 500 Internal Server error.

This might sound kind of weird but there's a lot of instances for wanting to do this. Example: remove all _ from URI and replace with -:

RewriteRule ^(.*)_(.*)$ /$1-$2 [L]

If the URI is /a_b_c_d_foo then the first time, the URI gets changed to /a_b_c_d-foo, then it loops and gets changed to `/a_b_c-d-foo, then again /a_b-c-d-foo and by the 5th time around you get /a-b-c-d-foo. It'll loop once more but since the ^(.*)_(.*)$ pattern doesn't match, the URI passes through the rewrite engine and the looping stops.

The problem arises when people create rules that don't take into account the looping, for example: rewrite /<anything> to /foo/<anything>:

RewriteRule ^(.*)$ /foo/$1 [L]

If the URI is /bar then the first time the URI gets rewritten to /foo/bar, and this is the desired result. But the URI gets internally redirected back into the rewrite engine and the same rule is matched again, resulting in: /foo/foo/bar, then again: /foo/foo/foo/bar, and again: /foo/foo/foo/foo/bar, until the internal recursion limit is reached and you get a 500 Server Error.



来源:https://stackoverflow.com/questions/15869322/what-is-the-precedence-of-multiple-mod-rewrite-rules-in-multiple-htaccess-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!