【问题标题】:Preserve HTTP/HTTPS protocol in .htaccess redirects在 .htaccess 重定向中保留 HTTP/HTTPS 协议
【发布时间】:2013-10-22 17:57:17
【问题描述】:

我必须在 htaccess 中将端口 80 重定向到 2368,但我想保持请求的协议完好无损,以免 SSL 中断。

我目前有这个:

RewriteCond %{HTTP_HOST} ^sub.domain.com$ [NC]
RewriteRule ^ http://sub.domain.com:2368%{REQUEST_URI} [P,QSA,L]

这可以正常工作,但如果可能,我希望从 %{HTTP_HOST} 条件中获取协议。

有没有办法在没有硬编码域和协议的情况下让它变得更加动态?

看起来很慢。

【问题讨论】:

    标签: .htaccess mod-rewrite rewrite


    【解决方案1】:

    Jon 提供的技巧是一个不错的 hack,但如果你想使用更多 [OR] 条件,我担心它可能会崩溃,如果你使用更多反向引用,你必须小心使用哪个数字 (%1%2 或..)。

    我认为smart HTTP/HTTPS handling 最优雅、健壮和干净的解决方案是设置一个变量:

    # initialization code - put only once at the beginning of .htaccess
    RewriteCond %{HTTPS} =on
    RewriteRule ^(.*)$ - [env=proto:https]
    RewriteCond %{HTTPS} !=on
    RewriteRule ^(.*)$ - [env=proto:http]
    
    # simply use %{ENV:proto} in your rules:
    RewriteCond %{HTTP_HOST} ^sub.domain.com$ [NC]
    RewriteRule ^            %{ENV:proto}://sub.domain.com:2368%{REQUEST_URI} [P,QSA,L]
    

    优点也是初始化代码只需要运行一次,所以如果你有更多的重写规则,那么生成的代码会更短更优雅。

    请注意,常见的设置是 cloudflare 提供的 https,在这种情况下,HTTPS 在服务器本身上不是“开启”的。在这种情况下,您需要额外的规则,例如(注意顺序):

    RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"' [OR]
    RewriteCond %{HTTPS} !=on
    RewriteRule ^(.*)$ - [env=proto:http]
    RewriteCond %{HTTP:CF-Visitor} '"scheme":"https"' [OR]
    RewriteCond %{HTTPS} =on
    RewriteRule ^(.*)$ - [env=proto:https]
    

    【讨论】:

    • 就我而言,它是%{ENV:HTTPS},但除此之外,太棒了!对于调试,您只需将 #%{HTTPS}-%{ENV:HTTPS}-%{ENV:proto} 附加到重定向目标并查看它的去向。
    • 设置环境变量 (^(.*)$) 的 RewriteRules 中的正则表达式变量 match 和 group 过多,应该删除,因为它实际上并没有在之后使用,而是使用破折号 (-)简单地通过。因此,例如,您只需要RewriteRule . - [env=...] 或类似名称。
    • 将原型保存在环境中是一个非常好的主意。当您需要多个 RewriteCond 反向引用时,这很有效,但显然这不起作用。
    【解决方案2】:

    从 Apache 2.4 开始,您还可以使用变量 %{REQUEST_SCHEME} 来保留方案:

    RewriteRule "^" "%{REQUEST_SCHEME}://sub.domain.com:2368%{REQUEST_URI}" [P,QSA,L]
    

    这样就不用多管闲事了。

    【讨论】:

      【解决方案3】:

      尝试添加如下条件:

      RewriteCond %{HTTPS} off [OR]
      RewriteCond %{HTTPS}:s on:(s) 
      

      检查 HTTPS 是关闭还是打开,您可以使用反向引用来获取“s”字符:

      RewriteCond %{HTTP_HOST} ^sub.domain.com$ [NC]
      RewriteCond %{HTTPS} off [OR]
      RewriteCond %{HTTPS}:s on:(s) 
      RewriteRule ^ http%1://sub.domain.com:2368%{REQUEST_URI} [P,QSA,L]
      

      所以如果 HTTPS 关闭,%1 为空白,协议为 http://。如果 HTTPS 开启,则“s”被分组,%1 反向引用为“s”,因此协议为 https://

      不过,这一切都假设端口 2368 可以处理未加密和 SSL/TLS。

      【讨论】:

      • 只是一个小评论。这不是重定向,这是由充当代理(P 标志)的服务器解决的。要进行实际重定向并要求客户端转到另一个 URL,您应该使用 R 标志而不是 P。
      【解决方案4】:

      或者,您可以使用the solution posted as an answer by Jon Lin 并将其重写为使用一个RewriteCond,然后设置一个变量as suggested in the answer by TMS

      看起来像这样:

      RewriteCond %{HTTPS}s ^(on(s)|offs)$
      RewriteRule ^ - [env=s:%2]
      
      RewriteCond %{HTTP_HOST} ^sub.domain.com$ [NC]
      RewriteRule ^ http%{ENV:s}://sub.domain.com:2368%{REQUEST_URI} [P,QSA,L]
      

      或者,如果您愿意:

      RewriteCond %{HTTPS}s ^(on(s)|offs)$
      RewriteRule ^ - [env=proto:http%2]
      
      RewriteCond %{HTTP_HOST} ^sub.domain.com$ [NC]
      RewriteRule ^ %{ENV:proto}://sub.domain.com:2368%{REQUEST_URI} [P,QSA,L]
      

      【讨论】:

      • ^(on(s)|offs)$ - 您可以将此正则表达式“简化”为 ^on(s)| 并改用 %1
      【解决方案5】:

      http 到 https 的重定向:

      <IfModule mod_rewrite.c>
          RewriteEngine On
          RewriteCond %{HTTPS} !on
          RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
      </IfModule>
      

      非 www 到 www 重定向:

      <IfModule mod_rewrite.c>
          RewriteEngine On
          RewriteCond %{HTTP_HOST} !^www\. [NC]
          RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
      </IfModule>
      

      如果你想同时使用这两个功能,那么将这两个代码块放在上面 适当的。

      【讨论】:

      • 虽然这不是问题所要求的。
      猜你喜欢
      • 2015-04-24
      • 2018-02-28
      • 1970-01-01
      • 2012-05-27
      • 2016-11-11
      • 1970-01-01
      • 2020-04-16
      • 2011-09-25
      • 1970-01-01
      相关资源
      最近更新 更多