apache url重写处理问号的核心是区分参数重写与路径转发,避免循环匹配;需用rewritecond排除真实文件目录,正则限定无点路径,配合l、qsa标志确保正确传递和终止。

Apache 处理带问号(?)的 URL 重写,核心在于区分两种场景:一种是把含查询参数的原始 URL(如 /?q=abc)重写为简洁路径(如 /abc),另一种是把路径形式的请求(如 /abc)内部转发给带参数的脚本(如 index.php?q=abc)。关键不是“匹配问号”,而是避免误匹配、防止循环重写,并正确传递参数。
避免正则过度匹配导致循环重写
常见错误是用 RewriteRule ^(.*) index.php?q=$1。它看似简单,但会出问题:
-
^.*匹配所有路径,包括index.php本身 - 第一次请求
/hello→ 重写为index.php?q=hello - 重写引擎再次处理
index.php→ 又匹配^.*→ 变成index.php?q=index.php - 最终
$_GET['q']得到的是index.php,而非预期内容
推荐写法:排除文件名和静态资源
用更精确的正则表达式,跳过真实存在的文件与后缀:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^.]*)$ index.php?q=$1 [L]
-
RewriteCond %{REQUEST_FILENAME} !-f:跳过已存在的文件(如style.css) -
RewriteCond %{REQUEST_FILENAME} !-d:跳过已存在的目录(如/images/) -
^([^.]*)$:只匹配不含点(.)的路径,自然排除index.php、logo.png等 -
[L]确保匹配后立即终止,不继续执行后续规则
保留原始查询参数(QSA 标志)
如果原始 URL 带有额外参数(如 /user/123?ref=ad),而你希望它们传给目标脚本,需加 [QSA]:
RewriteRule ^user/([0-9]+)$ user.php?id=$1 [QSA,L]
- 访问
/user/123?ref=ad→ 内部转发为user.php?id=123&ref=ad - 没有
QSA,ref=ad会被丢弃
强制跳转含问号的旧链接(301 重定向)
若需将旧的带参 URL(如 /search.php?q=test)永久跳转为新路径(如 /search/test),用 RewriteCond 判断查询字符串:
RewriteCond %{QUERY_STRING} ^q=([^&]+)$
RewriteRule ^search\.php$ /search/%1? [R=301,L]
-
%{QUERY_STRING}获取问号后的全部参数串 -
%1引用RewriteCond中第一个捕获组(即test) - 末尾的
?表示清空原始查询字符串,避免跳转后变成/search/test?q=test










