众所周知,用WP做url重写是非常方便的,只要在设置->固定链接里点点就能做出来了,nginx和apache需要修改配置文件和开启rewrite模块, IIS下甚至能直接给你生成web.config的重写文件,当然需要目录可写权限。

这次却遇到一些诡异的问题,站点服务器使用英文Windows 2008,PHP以 php-fcgi模式运行,IIS7.5,自带了url rewrite功能,url重写要求是使用/%postname%的形式,修改后,标题只有英文或数字组合的文章正常显示,点击中文标题的文章页不是循环重向定就是跳转到首页,从WP的启动流程开始一步步调试,结果发现IIS下在中文网址时对$_SERVER[‘REQUEST_URI’]获取的结果是如???dd???的形式,其实WP里有修正$_SERVER变量的函数,叫wp_fix_server_vars(),位于/wp-includes/load.php里,

执行条件为没有取得$_SERVER[‘REQUEST_URI’]或者PHP在IIS上以ISAPI执行时

if ( empty( $_SERVER['REQUEST_URI'] ) || ( php_sapi_name() != 'cgi-fcgi' && preg_match( '/^Microsoft-IIS//', $_SERVER['SERVER_SOFTWARE'] ) ) ) {
	// IIS Mod-Rewrite
		if ( isset( $_SERVER['HTTP_X_ORIGINAL_URL'] ) ) {
			$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_ORIGINAL_URL'];
		}
		// IIS Isapi_Rewrite
		else if ( isset( $_SERVER['HTTP_X_REWRITE_URL'] ) ) {
			$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL'];
		} else {
...
}

按理说 以php-fcgi执行的PHP应该不用执行这些修正的,然而很可惜,这里$_SERVER[‘REQUEST_URI’]是不对的,把条件设置成true执行完之后$_SERVER[‘REQUEST_URI’]可以得到修正,但这里有一个副作用,就是请求站点主页时会无限重定向,原因是修正时同时把$_SERVER[‘REQUEST_URI’]改为”index.php”。而正确的值应该为”/”,也就是说此时不需要作修正,而如果直接改WP源码也会对升级造成影响,于是可以考虑把它写入插件或主题的function里,仅当IIS重写时使用修正,当为请求主页时,即”/”,不会存在$_SERVER[‘HTTP_X_ORIGINAL_URL’]或$_SERVER[‘HTTP_X_REWRITE_URL’],因此不会修正$_SERVER[‘REQUEST_URI’],代码如下:

// 修正IIS的$_SERVER['REQUEST_URI']变量

add_action('plugins_loaded',"wp_fix_iis_server_vars");
function wp_fix_iis_server_vars(){
        if(preg_match( '/^Microsoft-IIS//', $_SERVER['SERVER_SOFTWARE'] ) ){
            // IIS Mod-Rewrite
            if ( isset( $_SERVER['HTTP_X_ORIGINAL_URL'] ) ) {
                $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_ORIGINAL_URL'];
            }
            // IIS Isapi_Rewrite
            else if ( isset( $_SERVER['HTTP_X_REWRITE_URL'] ) ) {
                $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL'];
            } 
        }    
}

- EOF -