apache rewrite规则不生效主因是mod_rewrite未启用或allowoverride未设为all;rewriterule匹配uri path不含query string,开头勿加/;[r]触发浏览器跳转,无[r]为内部重写;https与www重定向须分步且顺序合理。

rewrite规则不生效,.htaccess里写对了也没用?
绝大多数情况是 Apache 没启用 mod_rewrite 或没允许目录级重写。先确认模块已加载:a2enmod rewrite(Debian/Ubuntu),或检查 httpd.conf 中是否有 LoadModule rewrite_module modules/mod_rewrite.so。更关键的是,.htaccess 要起作用,对应目录必须有 AllowOverride All(不能是 None),且虚拟主机配置中未用 AllowOverride None 全局屏蔽。
常见错误现象:404 但日志里看不到 rewrite 日志;浏览器地址栏不变,但页面内容是错的;规则在本地测试正常,上线后失效。
-
RewriteEngine On必须出现在每段规则最前面,不能只写一次就以为全局生效 - 如果用
VirtualHost配置,优先改配置文件而非依赖.htaccess,性能更好、权限更可控 - 调试时加
RewriteLogLevel 3和RewriteLog "/path/to/rewrite.log"(Apache 2.2);2.4+ 改用RewriteLog已废弃,需用LogLevel alert rewrite:trace3
RewriteRule 匹配不到路径,正则怎么写才靠谱?
Apache 的 RewriteRule 默认只匹配 URI path 部分(不含 query string),且开头自动去掉当前上下文路径(比如在子目录 /blog/ 下,.htaccess 中的 ^post/(.*)$ 实际匹配的是 post/123,不是 /blog/post/123)。别直接复制 Nginx 或前端路由的正则——^/post/(\d+)$ 开头的 / 在 .htaccess 里会永远失败。
使用场景:把 /article/123 映射到 /index.php?id=123;隐藏 .php 后缀;强制 www 或 HTTPS。
- 路径开头不要加
/(.htaccess场景),写成^article/(\d+)$而非^/article/(\d+)$ - 要捕获 query string(如 ?ref=abc),得用
%{QUERY_STRING}配合RewriteCond,RewriteRule本身不处理它 - 末尾加
[L]表示“最后一条”,否则后续规则仍会执行,容易引发意外跳转 - 测试时用
[R=302]而非[R=301],避免浏览器缓存错误重定向
重定向(R)和内部重写(无 R)到底差在哪?
这是最容易混淆的点:加了 [R] 标志,浏览器地址栏会变,HTTP 状态码是 301/302;不加,只是服务器内部把请求悄悄转给另一个路径,用户完全感知不到。比如想把旧链接 /old.html 永久跳转到新地址,必须用 [R=301,L];而想让所有请求都由 index.php 统一处理(类似 Laravel 的 front controller 模式),就该用 [L] 不带 R。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
性能影响明显:301/302 重定向多一次 HTTP 往返;内部重写零额外网络开销,但要注意循环——比如规则把 / 重写成 /index.php,而 index.php 又被同一条规则再次匹配,就会触发 500 Internal Server Error。
- 判断依据看浏览器地址栏是否变化,以及开发者工具 Network 面板里状态码是不是 3xx
- 内部重写后,PHP 中
$_SERVER['REQUEST_URI']仍是原始路径,不是重写后的目标路径 - 用
[QSA](Query String Append)保留原有参数,比如从/user/123?tab=profile重写到/index.php?u=123,还要带上tab=profile,就得加[QSA]
HTTPS 强制跳转和 www 重定向组合写法容易出错
把 HTTP → HTTPS 和 non-www → www 合并在一个规则里看似简洁,实则极易陷入重定向循环,尤其当反向代理(如 Nginx、Cloudflare)存在时,%{HTTPS} 和 %{HTTP_HOST} 的值可能被代理头覆盖,导致条件误判。
正确做法是拆成两个独立逻辑块,并确保顺序合理:先协议跳转(HTTP→HTTPS),再域名规范(non-www→www),且每个块都用 [R=301,L] 终止。
- 别信 “一行搞定” 的写法,例如
RewriteCond %{HTTPS} off [OR]+RewriteCond %{HTTP_HOST} !^www\. [NC]—— 这个[OR]会让任意一个条件满足就跳转,可能把 HTTPS+non-www 错误跳到 HTTP+www - 检测 HTTPS 要谨慎:
%{HTTPS} != on在某些代理环境下不可靠,更稳妥的是检查%{HTTP:X-Forwarded-Proto} = http(需代理设置该 header) - 用
RewriteCond %{HTTP_HOST} ^example\.com$而非!^www\.,避免匹配到其他子域名(如api.example.com)也被误重定向
真实环境里,RewriteCond 的条件顺序、header 可信度、代理链路是否透传原始协议——这些细节比规则语法本身更容易导致线上故障。










