.htaccess规则在虚拟子目录不生效?URL重写失败求助
URL重写404问题排查与解决
需求
将 http://localhost/api/user/list?limit=10 重写为 http://localhost/api/index.php/user/list?limit=10,在线验证规则有效,但实际测试返回404错误。
已排查情况
- 在.htaccess中添加了响应头规则
Header set TEST_FOOBAR "oi" - 访问
http://localhost/api能看到该响应头 - 访问虚拟子目录
http://localhost/api/user时响应头消失 - 访问真实存在的目录
http://localhost/api/inc时能看到响应头 - 当前使用的.htaccess代码:
RewriteEngine On RewriteRule ^api(.*)$ /api/index.php$1 Header set TEST_FOOBAR "oi"
问题根源
- 规则匹配逻辑错误:如果.htaccess放在网站根目录,
^api(.*)$会匹配api开头的路径,但重写后的/api/index.php$1会导致路径拼接异常(比如/api/user被重写成/api/index.phpuser,缺少必要斜杠),直接引发404。 - .htaccess位置干扰:如果.htaccess放在
/api/目录下,^api(.*)$的匹配规则根本不会命中——此时请求路径是相对于/api/的,实际要匹配的是user而非api/user。 - 未排除真实资源:原规则没有排除真实存在的文件和目录,Apache可能优先访问真实资源,跳过重写规则。
修正方案
根据.htaccess的存放位置选择对应规则:
若.htaccess在网站根目录(localhost/.htaccess)
替换为以下规则:
RewriteEngine On # 排除真实存在的文件和目录,避免干扰正常访问 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # 正确截取/api/后的路径,重写到index.php后 RewriteRule ^api/(.*)$ /api/index.php/$1 [L] Header set TEST_FOOBAR "oi"
^api/(.*)$精准匹配/api/开头的路径,确保截取到user/list这类后续部分[L]标记表示执行完这条规则后停止后续重写,避免冲突- 两个
RewriteCond确保只有虚拟路径才会被重写,真实文件/目录不受影响
若.htaccess在/api/目录下(localhost/api/.htaccess)
替换为以下规则:
RewriteEngine On # 排除真实文件和目录 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # 匹配当前目录下所有虚拟路径,重写到index.php RewriteRule ^(.*)$ index.php/$1 [L] Header set TEST_FOOBAR "oi"
- 此时路径是相对于
/api/的,直接匹配^(.*)$即可获取user/list部分 - 同样通过条件排除真实资源,保证规则只作用于虚拟子目录
必查验证项
- 确认Apache已开启
mod_rewrite模块 - 检查网站配置文件(如httpd.conf)中,对应目录的
AllowOverride已设置为All,否则.htaccess规则不会生效 - 测试前清空浏览器缓存,避免旧缓存导致的异常
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

