如何配置htaccess RewriteRule规则捕获包含问号等特殊字符的完整URL参数
问题解决方法
问题根源
Apache的RewriteRule默认仅匹配请求URI中?之前的路径部分,?之后的内容会被识别为当前请求的查询字符串,不会被规则里的(.*)捕获,因此你要传递的目标URL里的?及后续内容会被默认拆分,不会被传入url参数。
解决方案
方案1:修改.htaccess重写规则(保留原有PHP代码不变)
调整重写规则,手动拼接被拆分的查询字符串到url参数中,同时添加相关标志处理特殊字符:
RewriteEngine On RewriteBase / # 处理目标URL带?和参数的场景 RewriteCond %{QUERY_STRING} .+ RewriteRule ^get/(.*)$ /get.php?url=$1?%{QUERY_STRING} [L,B,QSD] # 处理目标URL不带参数的场景 RewriteRule ^get/(.*)$ /get.php?url=$1 [L,B]
B标志:会自动转义URL中的特殊字符,避免&等符号被识别为参数分隔符QSD标志:丢弃原请求的查询字符串,避免重复附加到最终URL后
方案2:PHP直接解析完整请求URI(更稳定,推荐)
不需要处理复杂的重写参数传递逻辑,直接在PHP侧获取完整的请求URI切割出目标URL,兼容性更强,特殊字符、多层问号都不会丢失:
- 先简化.htaccess规则,只做请求转发不需要传参:
RewriteEngine On RewriteBase / RewriteRule ^get/.*$ /get.php [L]
- 修改get.php代码:
// 获取完整请求URI(包含?及后续所有内容) $fullUri = $_SERVER['REQUEST_URI']; // 去掉前缀/get/和可选的末尾斜杠 $targetUrl = preg_replace('#^/get/*#', '', $fullUri); $targetUrl = rtrim($targetUrl, '/'); print($targetUrl);
注意事项
如果传递的目标URL包含#等锚点字符,需要客户端先对整个目标URL做URL编码后再传递,因为锚点内容默认不会发送到服务端。
内容的提问来源于stack exchange,提问作者Ahmet Aytanozu
相关产品推荐
相关产品推荐

