apache mod_negotiation与MultiViews的奥妙

  2009-10-22


今天遇到一个奇怪的问题,取URL请求字符串时,明明访问的是/index/welcome/,取回来的却是/welcome/。
框架在处理这个问题时的处理流程是:

$php_self = $_SERVER[‘PHP_SELF’];
$uri = $_SERVER[‘REQUEST_URI’];

if (isset($_SERVER[‘PATH_INFO’])) {
$uri = $_SERVER[‘PATH_INFO’];
} else {
$uri = substr($uri, strlen(dirname($php_self)) );
}
$uri[0]!=’?’ || $uri = “/$uri”;
$uri = strtok($uri, ‘?’);

先判断PATH_INFO,然后再处理其他情况。
但我这里直接是http://xxx.com/index/welcome/ 怎么会存在PATH_INFO变量呢?
后来打印$_SERVER变量时发现,apache认为我访问的这个链接是/index.php/welcome/ !
原来apache可以在访问/path/foo时,如果找不到/path/foo,就会去找/path/foo.*,并且选一个合适的返回来,为你服务。
我这里存在着/index.php,所以访问/index/welcome/时,它就自动去找/index.php了!
而这些功能是一个模块提供的,它的名字叫mod_negotiation。相关说明:http://httpd.apache.org/docs/2.2/content-negotiation.html
同时,这个模块还提供了一个目录级别的控制开关,也就是<Directory段下的Options MultiViews,如果options中带有MultiViews字样,则启用这种功能,否则禁用。刚好,我的机器启用了mod_negotiation模块,并且Options中带有了MultiViews,所以出现了上面这种现象。

网上有很多相关的问题,但很多回复都没有回中点子上,比如:

http://www.phpx.com/happy/thread-125808-1-1.html

大多人都是想到用url rewrite来实现,呵呵。

其实,这个模块还有很多其他的强大功能,等待我们去发现,嘿嘿。