Redirecting www to non-www while maintaining the protocol HTTP or HTTPS

前端 未结 3 453
走了就别回头了
走了就别回头了 2021-01-15 05:56

I\'m attempting to redirect www to non-www for both HTTP and HTTPS requests. My root .htaccess looks like this:

RewriteEngine on

RewriteCond %{HTTP_HOST} ^w         


        
相关标签:
3条回答
  • 2021-01-15 06:19

    Perhaps you could try the following:

    RewriteEngine on
    
    # Check if the host contains "www."
    RewriteCond %{HTTP_HOST} ^www\.
    
    # Check if we're using HTTPS
    RewriteCond %{HTTPS}s ^on(s)|off
    RewriteCond http%1://%{HTTP_HOST} ^(https?://)(www\.)?(.+)$
    
    # Redirect accordingly
    RewriteRule ^ %1%3%{REQUEST_URI} [R=301,L]
    
    0 讨论(0)
  • 2021-01-15 06:31

    The first rule is taking precedence over https request because it simply met the rewrite condition. The first rule basically tells that match the domain and you can have your rewriterule to kick off. Instead add another condition which tells if its not https request

    So try this:

    RewriteEngine on
    
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteCond %{SERVER_PORT} !^443
    RewriteRule ^(.*)$ http://example.com/$1 [L,R=301]
    
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteCond %{SERVER_PORT} ^443
    RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]
    

    You need ssl certificate for https protocol to work

    Also I've added [L] flag which tells to not process further rules

    0 讨论(0)
  • 2021-01-15 06:42

    Inspired by @MikeRockétt's answer, this is a "simplified" version, using just one condition (instead of three). This also canonicalises a FQDN (ie. by removing an optional trailing dot on the hostname):

    RewriteEngine On
    
    RewriteCond %{HTTP_HOST}#%{HTTPS}s ^www\.(.+?)\.?#(?:on(s)|)
    RewriteRule ^ http%2://%1%{REQUEST_URI} [R=301,L]
    

    This 301 redirects www to non-www while maintaining the same protocol, HTTP or HTTPS. Can be used unaltered in either .htaccess (directory context) or in the main server config / vhost. (Although, if you are in a virtualhost context you should probably be using a simpler mod_alias Redirect instead.)

    Explanation:

    • The TestString %{HTTP_HOST}#%{HTTPS}s (which evaluates to a string of the form "www.example.com#ons") is compared against the CondPattern ^www\.(.+?)\.?#(?:on(s)|)

      • The condition is successful for any request whose Host header starts "www.".

      • ^www\.(.+?)\.? first checks that the Host starts with "www." (if not, it fails early) and captures the remaining host header (excluding an optional trailing dot) in the %1 backreference. The regex that captures the domain name, ie. (.+?) is made non-greedy so that it does not capture the optional dot at the end.

      • # is just an arbitrary character that is used to separate the two values HTTP_HOST and HTTPS. Importantly, # cannot itself appear in either of these two values.
      • (?:on(s)|) is a non-capturing group that uses alternation to match against %{HTTPS}s. It either matches on(s) and captures the "s" (in the %2 backreference) or it matches anything and captures nothing (so %2 is empty).
    • Providing the previous condition is successful then the substitution string (http%2://%1%{REQUEST_URI}) is evaluated and the request redirected. The backreference %2, from the preceding CondPattern, either holds an "s" (to make "https" in the substitution) or is empty (ie. "http") and %1 is the hostname less the "www." prefix.

    • The REQUEST_URI server variable holds the full URL-path, including the slash prefix.

    must my server have an SSL certificate?

    Yes, otherwise the browser will block the connection (complaining about an invalid security certificate) - or simply time-out (because your server is not responding on port 443) and the request will not even reach your server.

    0 讨论(0)
提交回复
热议问题