含REQUEST_URI的.htaccess重定向:URL混入服务器文件夹路径的原因与解决
问题背景
我们在共享主机服务器上承接了一项需求:保留客户域名在其自有服务器,但将Web流量的DNS指向我方服务器。我方在根目录的.htaccess中添加规则,将example.pl域名的请求转发到服务器内/WebsitesLive/Example/文件夹:
RewriteCond %{HTTP_HOST} ^(www\.)?example\.pl$ [NC] RewriteCond %{REQUEST_FILENAME} !/WebsitesLive/Example/ RewriteRule ^(.*)$ /WebsitesLive/Example/$1 [L]
网站运行正常,但Google Analytics显示有部分用户通过https://example.pl/WebsitesLive/Example访问。推测问题出在客户站点.htaccess中的HTTPS与非www重定向规则:
RewriteCond %{HTTPS} !on RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
核心问题解答
1. %{REQUEST_URI}是否会包含WebsitesLive/Example?
会包含。%{REQUEST_URI}是Apache在执行内部重写规则后更新的变量,当内部转发规则把请求指向/WebsitesLive/Example/$1后,这个变量就会带上该路径。如果此时触发HTTPS重定向(比如用户用HTTP访问),重定向URL就会拼接这个已被修改的%{REQUEST_URI},导致用户看到带WebsitesLive/Example的地址。
2. 如何阻止这种情况发生?
提供三种可行方案,按优先级排序:
方案一:调整规则执行顺序
将HTTPS/非www重定向规则放在内部转发规则之前,这样重定向时还未执行内部转发,%{REQUEST_URI}保持用户原始请求的干净路径。修改后的.htaccess内容如下:
# 优先处理HTTPS重定向 RewriteCond %{HTTPS} !on RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] # 再执行域名到目录的内部转发 RewriteCond %{HTTP_HOST} ^(www\.)?example\.pl$ [NC] RewriteCond %{REQUEST_FILENAME} !/WebsitesLive/Example/ RewriteRule ^(.*)$ /WebsitesLive/Example/$1 [L]
方案二:使用原始请求路径变量
如果无法调整规则顺序,改用%{THE_REQUEST}变量提取用户原始请求路径——这个变量记录的是用户最初发送的请求行,不会被内部重写修改。修改HTTPS重定向规则:
RewriteCond %{HTTPS} !on RewriteCond %{THE_REQUEST} ^[A-Z]+\s+(/[^?\s]*)\s RewriteRule ^ https://%{HTTP_HOST}%1 [R=301,L]
%{THE_REQUEST}格式类似GET /some/path HTTP/1.1,正则会提取出/some/path部分并通过%1引用,确保重定向URL是用户原本请求的路径。
方案三:添加路径清理规则
针对已经出现的带WebsitesLive/Example的访问地址,添加规则强制重定向回干净域名,同时修正Analytics记录:
RewriteCond %{HTTP_HOST} ^(www\.)?example\.pl$ [NC] RewriteRule ^WebsitesLive/Example/(.*)$ /$1 [R=301,L]
该规则会将https://example.pl/WebsitesLive/Example/xxx重定向到https://example.pl/xxx。
内容的提问来源于stack exchange,提问作者Moseleyi

