I have used the http protocol for a long time. After years I implemented a domain certificate. Now I am trying to get the website with the https:// protocol indexed but Google still indexes the http protocol.
I have tried several things. I enabled the 'Force SSL with https redirect' option in DirectAdmin.
I changed my .htaccess so the browser redirects every option to the https protocol:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^[^.]+\.[^.]+$
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RedirectMatch permanent index.php/(.*) https://www.***.com/$1
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.(php|html) [NC]
RewriteRule ^index\.php$ https://www.***.com/ [R=301,L]
RewriteCond %{THE_REQUEST} ^GET\ /.*/index\.(php|html)\ HTTP
RewriteRule (.*)index\.(php|html)$ /$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^domain\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.domain\.com$
RewriteRule ^home\.html$ "https\:\/\/www\.domain\.com\/" [R=301,L]
RewriteCond %{HTTP_HOST} ^domain\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.domain\.com$
RewriteRule ^home$ "https\:\/\/www\.domain\.com\/" [R=301,L]
I have created a sitemap.xml that contains only the https:// protocol.
In the Google Search Console I see that the website is indexed today and that the 'Google selected canonical URL' is still the http protocol.
Does someone know what I need to do to fix this problem?
I changed my .htaccess so the browser redirects every option to the https protocol:
Actually, you've not.
You don't have an HTTP to HTTPS redirect at all and the first rule (a non-www to www redirect) specifically maintains whatever protocol has been requested (HTTP or HTTPS).
Try the following two rules instead, replacing your first (non-www to www) rule:
# non-www to www (and HTTPS)
RewriteCond %{HTTP_HOST} ^[^.]+\.[^.]+$
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# HTTP to HTTPS (already www)
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
The remaining directives can also be simplified...
# Redirect to path-info (removing "index.php")
RewriteRule ^(.+/)?index\.php/(.*) /$1 [R=301,L]
# Remove "index.php" from the end of the URL
RewriteRule ^(.+/)?index\.php$ /$1 [R=301,L]
# Redirect "home" and "home.html" to the document root
RewriteRule ^home(\.html)?$ / [R=301,L]
You don't seem to need to target the domain name in the later directives, so I've removed the seemingly superfluous conditions.
I've simplified/reduced the two rules that removed index.php into a single directive. Unless you have a front-controller whereby you are routing all requests to index.php then you don't need the additional condition that checks against THE_REQUEST. (There is no front-controller in the directives you've posted.)
(Although the rule that removes and redirects to the path-info is a little out of place if you don't have a front-controller?)
I've changed the mod_alias RedirectMatch to the corresponding*1 mod_rewrite rule. mod_alias directives are processed after mod_rewrite, despite the apparent order of directives in the config file, so it is advisable to avoid mixing redirects from both modules to avoid unexpected conflicts.
(*1 I've also "corrected" this so to avoid matching URLs of the form <anything>index.php, rather than <anything>/index.php, which I assume is the intention.)
Clear your browser cache and test first with 302 (temporary) redirects to avoid any potential caching issues.
I also tried to delete the canonical link element
You should not delete the "canonical link element" providing you are linking to the correct canonical URL, ie. HTTPS + www.
You've not actually stated how long it is since you've "switched to HTTPS", but this can take some time. Google naturally favours HTTPS, but you are likely to have many HTTP backlinks due to the age of your site. It is important that you 301 redirect HTTP to HTTPS.
You should register both properties: HTTP and HTTPS in GSC and monitor the index status of both.
NB: Questions of this nature are generally better asked on the Webmasters stack: https://webmasters.stackexchange.com/
Related
I have seen couple of solutions to 301 redirect non www http i.e. http://domain-name to https://www.domain-name but all of them (in my experience) gives 2 redirects.
Either they first redirect from non www to www first and than http to https or in 2nd redirect first and than 1st redirect. One of the example of such code is:
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.example.com%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
The best solution would be one 301 redirect which takes care of both i.e. non www as well as http part. Can anyone please suggest me the right code.
Best rgds,
Jai
I am using this code and I get only one 301 redirect (to https://www.example.com) when I test http://example.com with httpstatus.io
# ensure www
RewriteCond %{HTTP_HOST} !^www.example.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]
# ensure https
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
The first rule, if your address doesn't start with www will be redirected to the https + www (one redirect)
The second rule applies only if your address starts with a www (because of rule 1) and it doesn't contain https. (one redirect)
Indeed, your domain http://infocera.com is getting 2 redirects.
Using #MrWhite's suggestion about your domain going through Cloudflare: you should go to your domain in Cloudflare -> Rules -> Page Rules and delete any rule you have about redirecting.
I suggest to combine both rules into a single one by combining both conditions:
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\. [OR]
RewriteCond %{HTTPS} off
RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]
That is simple, thus easy to understand for anyone maintaining the site.
The only drawback would be that you have to specify a fixed http host in the target rule. Which is perfectly fine except if you host multiple domains and hope to find a solution working for all of them at once.
I would generally advise against such an attempt though. Such general rules have nothing to do with an application logic, one should always prefer to implement such general rule in the actual http server's host configuration instead of using distributed configuration files (".htaccess"). That means that you have separate configurations for separate domains, which again allows to place such rule into the separate configuration files while still having only a single actual redirection that is performed.
I have this rule to switch all http connections to https. Edited to show the whole file
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.example\.kiwi$ [OR]
RewriteCond %{HTTP_HOST} ^example\.nz$ [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.nz$
RewriteRule ^/?$ "https\:\/\/example\.kiwi\/$1" [R=301,L]
RewriteCond %{HTTP_HOST} ^example\.app$ [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.app$
RewriteRule ^/?$ "https\:\/\/example\.kiwi\/$1" [R=301,L]
RewriteCond %{HTTP_HOST} ^example\.online$ [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.online$
RewriteRule ^/?$ "https\:\/\/example\.kiwi\/$1" [R=301,L]
RewriteCond %{HTTP_HOST} ^example\.software$ [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.software$
RewriteRule ^/?$ "https\:\/\/example\.kiwi\/$1" [R=301,L]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
Header always set Content-Security-Policy "upgrade-insecure-requests;"
Header always setifempty Strict-Transport-Security "max-age=31536000" env=HTTPS
Header append X-Frame-Options: "SAMEORIGIN"
Unfortunately it affects things like mail.domain.com (and others). How do I stop any/all subdomains from being upgraded ?
Assuming you only want to redirect the www subdomain and the domain apex to HTTPS then you can check the Host header in a RewriteCond directive.
For example:
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
The above will only redirect www.example.com or example.com.
I've removed the capturing group in the RewriteRule pattern (ie ^(.*)$) since it's not being used here.
Test with a 302 (temporary) redirect to avoid caching issues.
You will need to clear your browser cache before testing.
Also consider canonicalising the hostname (www vs non-www) in the redirect also.
Header always set Content-Security-Policy "upgrade-insecure-requests;"
However, since not everything is now HTTPS, if you are loading resources from the subdomains over HTTP then this header should be sent conditionally, based on whether the request was over HTTPS to begin with.
For example, on Apache 2.4.10+ you can use Apache expression syntax in the Header directive:
Header always set Content-Security-Policy "upgrade-insecure-requests;" "expr=%{HTTPS} == 'on'"
UPDATE:
I want different suffixes to work such as example.software and example.app, so should I replace the ".com" with ".?"
You could simply remove the TLD in the regex in the first condition. For example:
RewriteCond %{HTTP_HOST} ^(www\.)?example\. [NC]
This will now match example.com, example.software, www.example.app etc. But it will fail if you happen to have a subdomain the same name as the domain itself (eg. example.example.com) - but that should be avoided.
I have edited the post to show my whole file, in case there are side-effects. I have a number of domains that are all being redirected for the moment while the website is getting constructed.
This doesn't affect the HTTP to HTTPS redirect. These directives redirect all the other domains to https://example.kiwi - so when these directives are processed the later HTTP to HTTPS redirect is bypassed (not required) anyway.
However, there are a couple of issues with these redirects.
"redirected for the moment" - You imply that these redirects are temporary, but you are using a 301 (permanent) response. This results in the redirect being cached persistently, which can be impossible to undo. If this is temporary then it should be a 302 (temporary) redirect.
^/?$ - You are only redirecting requests for the document root (ie. the homepage). A request for example.nz/foo will not be redirected. This further looks like an error because you are using a $1 backreference in the substitution string, which will consequently always be empty.
These redirect directives could also be greatly simplified. If you are "temporarily" redirecting all other domains to https://example.kiwi/<url> then you could do it with a single rule like this instead:
RewriteCond %{HTTP_HOST} !=example.kiwi
RewriteRule ^ https://example.kiwi%{REQUEST_URI} [R=302,L]
Where !=example.kiwi is a negated exact match string comparison (not a regex). The condition is successful then the Host header does not match example.kiwi.
Aside:
Header always setifempty Strict-Transport-Security "max-age=31536000" env=HTTPS
You shouldn't be implementing HSTS whilst still in development and changing domains. However, you don't appear to be setting an HTTPS env var in the code you have posted, so this is likely being ignored anyway. (?)
NB: env=HTTPS is not checking the server variable of the same name.
We have installed a SSL for our site and I have created an .htaccess with the following code:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# mobile redirect
RewriteCond %{HTTP_HOST} ^www\mobile.example\.com [NC]
RewriteCond %
{HTTP_USER_AGENT}"android|blackberry|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteRule ^(.*)$ https://mobile.example.com/$1 [L,R=302]
</IfModule>
This code works great coming from the desktop, but the mobile part is not working. What am I missing?
...but the mobile part is not working.
You've not stated explicitly what the "mobile" part is expected to do. However, the "mobile part" in your code would seem to just be a www to non-www redirect. The HTTP to HTTPS redirect is separate to this and does not differentiate between mobile and desktop (and neither would it necessarily need to).
However, there are several issues with the directives in the "mobile part" that will prevent it from "working" (and also with the HTTP to HTTPS redirect).
The directives are in the wrong order. Both of the external redirects (HTTP to HTTPS and "mobile" www to non-www) should be before the internal rewrite (the first couple of rules)
I assume ENV:HTTPS (that references an environment variable called HTTPS) is as per instruction from your webhost. This is non-standard, although not uncommon with some shared hosts.
RewriteCond %{HTTP_HOST} ^www\mobile.example\.com [NC] - You are missing a dot after the www subdomain (assuming that is what you trying to match). So, this will never match. You are also missing a slash before the dot in the middle of the regex (to match a literal dot, not any character). The CondPattern should presumably read ^www\.mobile\.example\.com in order to match the www subdomain.
RewriteCond % {HTTP_USER_AGENT}"android|blackberry|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC] - You are missing a space after the first argument %{HTTP_USER_AGENT}<here>. Although you also appear to have an erroneous space after the %. Either way, this will fail to match. However, I would also question why you specifically need to match the mobile user-agent here? I would think you need to redirect www to non-www regardless of user-agent? Why would you permit a desktop user-agent access to www.mobile.example.com? So, this condition can perhaps be removed entirely.
Not a bug, but you probably don't need the <IfModule> wrapper, unless these directives are optional and you are porting the same code to multiple servers where mod_rewrite might not be available. See my answer to a related question on the Webmasters stack: https://webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary
Again, not a bug, but the RewriteBase / directive in this block of code is entirely redundant.
Taking the above points into consideration, it should be written more like this:
RewriteEngine On
# HTTP to HTTPS redirect - all hosts
RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# mobile redirect
RewriteCond %{HTTP_HOST} ^www\.mobile\.example\.com [NC]
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteRule (.*) https://mobile.example.com/$1 [R=302,L]
# Front-controller
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
Like I said in the notes above, I question the use of the RewriteCond %{HTTP_USER_AGENT} directive to detect mobile-only user-agents. If all users should be redirected www to non-www (as it looks like they should) then simply remove this condition. This should also presumably be a 301 (permanent) redirect once you have confirmed that it works as intended.
Taking this a step further, don't you also want to canonicalise desktop clients as well? ie. Redirect www to non-www on all hosts?
This code works great coming from the desktop
Although there's no reason why this didn't work "great" from mobile either if you were requesting the conanical host, ie. https://mobile.example.com/.
UPDATE: What I need for the .htaccess to do is redirect all traffic - desktop and mobile etc - to the new https instead of HTTP.
By the sounds of it you only need a "simple" HTTP to HTTPS redirect. The "front-controller pattern" that you have seemingly copied from the webhost's article may be in error?
Try the following instead in the root .htaccess file.
RewriteEngine On
# Redirect all requests from HTTP to HTTPS on the same host
RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
You should remove all other directives and make sure there are no other .htaccess files in subdirectories.
The REQUEST_URI server variable contains the requested URL-path. This will be required, instead of using a backreference as you had initially, if your mobile subdomain points to a subdirectory off the main domain's document root (which you hint at in comments, but not stated in the question).
You must clear the browser cache before testing and test first with 302 (temporary) redirects before changing to a 301 (permanent) redirect only once you have confirmed the redirect works as intended.
I have working code in .htaccess that accomplishes the following.
redirect non-www to www (and https:)
redirect http to https (and www)
allow accessing URLs ending with /file1.htm etc at /file
However, as I discovered, the third rule was more of a hack that needed to be used in combination with removing all existing links to the .htm versions (which is outside your control). As a result, Google started crawling both versions and deciding which ones are canonical.
I want to modify the third rule to not just allowing access at /file, but rewriting the URL with a 301 message. There are several answers on Stackoverflow that have worked for others that are not working for me due to existing rules in the file, so I'm posting it as a new question.
How do I add a 301 redirect to all /file.htm links to /file without breaking the 3 existing rules?
RewriteEngine On
RewriteCond %{http_host} ^example.com [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.htm [NC,L]
Redirect 301 /output.php /
I want to modify the third rule to not just allowing access at /file, but rewriting the URL with a 301 message.
Using a 301 there makes little sense – you want to keep this one an internal redirect.
You should add a new rule, that rewrites requests for /file.htm to /file externally, and have that one use a 301 status code:
#1) externally redirect "/file.htm" to "/file"
RewriteCond %{THE_REQUEST} /([^.]+)\.htm [NC]
RewriteRule ^ /%1 [NC,L,R=301]
#2) Internally map "/file" back to "/file.htm"
RewriteCond %{REQUEST_FILENAME}.htm -f
RewriteRule ^(.*?)/?$ /$1.htm [NC,L]
I am currently using this .htaccess to redirect all the requests for pages with a directory to my index.php
RewriteEngine on
RewriteCond $1 !^(index\.php|cas)
RewriteRule ^(.*)$ /seattle/index.php/$1 [L]
And this works just fine and produces urls that hide the index.php, and I have code in index.php that makes urls clean looking.
But now I need to force pages to connect via ssl, so I tried
RewriteEngine on
RewriteCond %{SERVER_PORT} 80
RewriteCond $1 !^(index\.php|cas)
RewriteRule ^(.*)$ https://example.com/seattle/index.php/$1 [L]
and it works to force ssl, but now it also forces the url to include the index.php:
https://example.com/seattle/index.php/pagename
instead of what I want
https://example.com/seattle/pagename
What am I missing?
To change protocol (HTTP -> HTTPS) and/or domain name (www.example.com -> example.com) the proper redirect ("301 Permanent Redirect" or "302 Found/Temp Redirect") is required.
Therefore you cannot combine rewrite and redirect and still showing original URL. It has to be 2 different rules and the one for changing protocol/domain should be listed first. For example:
RewriteEngine on
# force HTTPS for all URLs
RewriteCond %{HTTPS} =off
RewriteRule . https://example.com%{REQUEST_URI} [R=301,L]
# other rewrite rules
RewriteCond $1 !^(index\.php|cas)
RewriteRule ^(.*)$ /seattle/index.php/$1 [L]
The rule I have added will redirect ALL HTTP URLs to HTTPS. If you need only some of them to be redirected -- add appropriate conditions via additional RewriteCond line(s).
The %{HTTPS} is the most common and kind of "proper" way of checking if SSL is ON or OFF (but it is all depending on your specific circumstances and server config). When checking against %{HTTPS} you are safe against situation when your site is running on non-standard port (other than 80). You can use %{SERVER_PORT} =80 instead (will work for majority of cases).
With the above rules the rewrite for http://example.com/seattle/pagename will occur in 2 steps:
301 Redirect to https://example.com/seattle/pagename
Rewrite (internal redirect) to /seattle/index.php/pagename