http > https 错误的最终 url(子域重定向)
http > https wrong final url (subdomain redirect)
我有:
目录树:
└───domains
├───bar.com
│ ├───sub (sub.bar.com / www.sub.bar.com)
│ ├───sub2 (sub2.bar.com / www.sub2.bar.com)
│ └───www (bar.com / www.bar.com)
└───foo.com
├───sub (sub.foo.com / www.sub.foo.com)
├───sub2 (sub2.foo.com / www.sub2.foo.com)
└───www (foo.com / www.foo.com)
/.htaccess
RewriteEngine On
# remove www from URL
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/ [R=301,DPI,L,NC]
# subdomains (sub.foo.com, sub.bar.com, sub2.foo.com, sub2.bar.com)
RewriteCond %{REQUEST_URI} !^domains/
RewriteCond %{REQUEST_URI} !^/domains/
RewriteCond %{HTTP_HOST} ^([^\.]*)\.([^\.]*\.[^\.]*)$
RewriteCond %{DOCUMENT_ROOT}/domains/%2 -d
RewriteCond %{DOCUMENT_ROOT}/domains/%2/%1 -d
RewriteRule (.*) /domains/%2/%1/ [DPI]
# main domains (foo.com, bar.com)
RewriteCond %{REQUEST_URI} !^domains/
RewriteCond %{REQUEST_URI} !^/domains/
RewriteCond %{HTTP_HOST} ^([^\.]*\.[^\.]*)$
RewriteCond %{DOCUMENT_ROOT}/domains/%1 -d
RewriteRule (.*) /domains/%1/www/ [DPI]
这看起来工作得很好,但是当我需要在 foo.com
上启用 https 时,它并没有按预期工作。
/domains/foo.com/.htaccess
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [DPI,R=301]
因为不是重定向:http://www.sub.foo.com/?query > https://sub.foo.com/?query it redirect to: https://sub.foo.com/domains/foo.com/sub/?query 但它确实不是我所期望的。
/domains/foo.com/.htaccess
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [DPI,R=301]
这在 /domains/foo.com/.htaccess
文件中使用时无法按预期工作,因为它正在处理 URL 已被 /.htaccess
文件在根目录中,到这个阶段 REQUEST_URI
服务器变量已经更新为请求已重写到的完整 URL 路径(不是 URL用户请求),即。 /domains/foo.com/sub/
.
(旁白: 你没有说明你是否在使用 PHP, 但为了以防万一... REQUEST_URI
PHP 超全局变量,即 $_SERVER['REQUEST_URI']
),与 REQUEST_URI
Apache 服务器变量不同。 REQUEST_URI
PHP 变量包含用户请求的 URL (这似乎是您对 Apache 服务器变量的期望),在这种情况下与 Apache 不同同名的服务器变量。)
简单的解决方案是从匹配 RewriteRule
模式 的 URL 路径中捕获 URL 路径,而不是使用 REQUEST_URI
Apache 服务器变量。
例如:
# /domains/foo.com/.htaccess
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}/ [R=301,L]
在 .htaccess
中,RewriteRule
模式 匹配 URL-path 减去目录前缀 - 所以它总是相对的到包含 .htaccess
文件的目录。
这里似乎不需要 DPI
标志。
替代解决方案是将您的 HTTP 到 HTTPS 重定向移动到根 /.htaccess
文件( 在 内部重写之前)并且可能检查请求的 hostname 如果需要有选择性的话。例如:
# /.htaccess
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^(www\.)?sub\.foo\.com [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
在根 /.htaccess
文件中,我们可以使用 Apache 变量 REQUEST_URI
,前提是将重定向放在 之前 内部重写。
您需要在测试前清除浏览器缓存。最好使用 302(临时)重定向进行测试,以避免潜在的缓存问题。
# remove www from URL
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/ [R=301,DPI,L,NC]
另一个 "problem" 是您的 www 到非 www 重定向总是重定向到 HTTP。因此,对 https://www.sub.foo.com/
的请求将在(希望)被重定向回 HTTPS 之前被重定向回 HTTP——这是一个不必要的额外重定向。根据您的要求,您可以通过多种方式解决此问题。
我有:
目录树:
└───domains
├───bar.com
│ ├───sub (sub.bar.com / www.sub.bar.com)
│ ├───sub2 (sub2.bar.com / www.sub2.bar.com)
│ └───www (bar.com / www.bar.com)
└───foo.com
├───sub (sub.foo.com / www.sub.foo.com)
├───sub2 (sub2.foo.com / www.sub2.foo.com)
└───www (foo.com / www.foo.com)
/.htaccess
RewriteEngine On
# remove www from URL
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/ [R=301,DPI,L,NC]
# subdomains (sub.foo.com, sub.bar.com, sub2.foo.com, sub2.bar.com)
RewriteCond %{REQUEST_URI} !^domains/
RewriteCond %{REQUEST_URI} !^/domains/
RewriteCond %{HTTP_HOST} ^([^\.]*)\.([^\.]*\.[^\.]*)$
RewriteCond %{DOCUMENT_ROOT}/domains/%2 -d
RewriteCond %{DOCUMENT_ROOT}/domains/%2/%1 -d
RewriteRule (.*) /domains/%2/%1/ [DPI]
# main domains (foo.com, bar.com)
RewriteCond %{REQUEST_URI} !^domains/
RewriteCond %{REQUEST_URI} !^/domains/
RewriteCond %{HTTP_HOST} ^([^\.]*\.[^\.]*)$
RewriteCond %{DOCUMENT_ROOT}/domains/%1 -d
RewriteRule (.*) /domains/%1/www/ [DPI]
这看起来工作得很好,但是当我需要在 foo.com
上启用 https 时,它并没有按预期工作。
/domains/foo.com/.htaccess
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [DPI,R=301]
因为不是重定向:http://www.sub.foo.com/?query > https://sub.foo.com/?query it redirect to: https://sub.foo.com/domains/foo.com/sub/?query 但它确实不是我所期望的。
/domains/foo.com/.htaccess
RewriteEngine On RewriteCond %{HTTPS} !=on RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [DPI,R=301]
这在 /domains/foo.com/.htaccess
文件中使用时无法按预期工作,因为它正在处理 URL 已被 /.htaccess
文件在根目录中,到这个阶段 REQUEST_URI
服务器变量已经更新为请求已重写到的完整 URL 路径(不是 URL用户请求),即。 /domains/foo.com/sub/
.
(旁白: 你没有说明你是否在使用 PHP, 但为了以防万一... REQUEST_URI
PHP 超全局变量,即 $_SERVER['REQUEST_URI']
),与 REQUEST_URI
Apache 服务器变量不同。 REQUEST_URI
PHP 变量包含用户请求的 URL (这似乎是您对 Apache 服务器变量的期望),在这种情况下与 Apache 不同同名的服务器变量。)
简单的解决方案是从匹配 RewriteRule
模式 的 URL 路径中捕获 URL 路径,而不是使用 REQUEST_URI
Apache 服务器变量。
例如:
# /domains/foo.com/.htaccess
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}/ [R=301,L]
在 .htaccess
中,RewriteRule
模式 匹配 URL-path 减去目录前缀 - 所以它总是相对的到包含 .htaccess
文件的目录。
这里似乎不需要 DPI
标志。
替代解决方案是将您的 HTTP 到 HTTPS 重定向移动到根 /.htaccess
文件( 在 内部重写之前)并且可能检查请求的 hostname 如果需要有选择性的话。例如:
# /.htaccess
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^(www\.)?sub\.foo\.com [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
在根 /.htaccess
文件中,我们可以使用 Apache 变量 REQUEST_URI
,前提是将重定向放在 之前 内部重写。
您需要在测试前清除浏览器缓存。最好使用 302(临时)重定向进行测试,以避免潜在的缓存问题。
# remove www from URL RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] RewriteRule ^(.*)$ http://%1/ [R=301,DPI,L,NC]
另一个 "problem" 是您的 www 到非 www 重定向总是重定向到 HTTP。因此,对 https://www.sub.foo.com/
的请求将在(希望)被重定向回 HTTPS 之前被重定向回 HTTP——这是一个不必要的额外重定向。根据您的要求,您可以通过多种方式解决此问题。