【问题标题】:http > https wrong final url (subdomain redirect)http > https 错误的最终 url(子域重定向)
【发布时间】:2020-02-03 23:15:06
【问题描述】:

我有:

目录树:

└───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/$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/$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/$1 [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 它重定向到:https://sub.foo.com/domains/foo.com/sub/?query,但这确实不是我所期望的。

【问题讨论】:

    标签: regex apache .htaccess mod-rewrite http-redirect


    【解决方案1】:

    /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 服务器变量不同。)

    简单的解决方案是从RewriteRulepattern 匹配的 URL-path 中捕获 URL-path,而不是使用 REQUEST_URI Apache 服务器变量。

    例如:

    # /domains/foo.com/.htaccess
    RewriteEngine On
    RewriteCond %{HTTPS} !=on
    RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]
    

    .htaccess 中,RewriteRule 模式 匹配减去目录前缀的 URL 路径 - 因此它始终与包含 .htaccess 文件的目录相关。

    这里似乎不需要DPI 标志。

    另一种解决方案是将您的 HTTP 到 HTTPS 重定向到根 /.htaccess 文件(内部重写之前),如果您可能会检查请求的 主机名需要有选择性。例如:

    # /.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/$1 [R=301,DPI,L,NC]
    

    另一个“问题”是您的 www 到非 www 重定向总是重定向到 HTTP。因此,https://www.sub.foo.com/ 的请求将在(希望)被重定向回 HTTPS 之前被重定向回 HTTP - 不必要的额外重定向。根据您的要求,您可以通过多种方式解决此问题。

    【讨论】:

      猜你喜欢
      • 2016-03-20
      • 2012-02-15
      • 2015-08-26
      • 2016-01-30
      • 1970-01-01
      • 2019-03-03
      • 1970-01-01
      • 1970-01-01
      • 2020-04-21
      相关资源
      最近更新 更多