.htaccess www to non-www while keeping path, ssl, and query string - apache

I'm trying to achieve the following in .htaccess:
redirect www to non-www
keep the path that has been requested (e.g. domain.com/path/to/file.php)
keep the query string, if any (e.g. domain.com/path/to/file.php?key=val&key2=val2)
keep the protocol that has been requested (either http or https)
I tried this code:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^domain\.com$ [NC]
RewriteRule ^(.*)$ http://domain.com/$1 [R=301,L]
but it doesn't respect http/https, nor does it keep the path that has been requested (e.g. it redirects https://www.domain.com/path/file.php to http://domain.com/file.php, when it should redirect to https://domain.com/path/file.php instead.)
Any ideas?

You need to check if a request is http or https, and redirect to the correct protocol. Right now, you're redirecting everything to http://. You can use this condition and grouping:
RewriteCond %{HTTPS}:s (on:(s)|off:s)
This uses the %{HTTPS} variable, which is either "on" or "off", and pairs it with an s. Then we match either on:(s) or off:s. Therefore, if HTTPS is "on", the (s) gets grouped and we can backrefernce it using a %2, otherwise, if HTTPS is "off", nothing gets grouped and %2 is blank. We can then use it in your redirect:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^domain\.com$ [NC]
RewriteCond %{HTTPS}:s (on:(s)|off:s)
RewriteRule ^(.*)$ http%2://domain.com/$1 [R=301,L]
As for the second thing about the paths not being preserved, it sounds like your rules are in the directory /path, which means it gets stripped off when it gets sent through these rules. You need to move them to your document root. Alternatively, if you must have your rules in the /path directory, you can use the %{REQUEST_URI} variable instead:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^domain\.com$ [NC]
RewriteCond %{HTTPS}:s (on:(s)|off:s)
RewriteRule ^ http%2://domain.com%{REQUEST_URI} [R=301,L]

Related

How to redirect a url that ends with html to https non-www version, while also retrieve the content from a specific php files?

i am still new to htaccess. I have a static website, that has a content inside several directories. I use this to redirect 301 all html pages to its https non-www version.
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule (.*) https://example.com/$1 [L,R=301]
I want the website to be dynamic. So after it redirects to https non-www version, i want it to grab the resources from a specific php files. But, i don't know how to do that, while also do the first 301 redirect.
I try to grab the resources by using something like:
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule (.*) https://example.com/$1
RewriteRule (.*)/(.*)/(.*)\.html$ https://note.mathpro.id/$2.php?name=$3 [L,R=302]
This URL http://example.com/category/uncategorized.html retrieves the content from https://example.com/category.php?name=uncategorized, but doesn't redirect it to https://example.com/category/uncategorized.html as it intially did.
Can anyone help?
... i don't know how to do that, while also do the first 301 redirect.
These are two entirely separate tasks that requires two different rules. You should not modify the first (canonical redirect) rule. (For some reason, you have removed the flags argument, ie. [L,R=301] - The L flag is required for the redirect to function as intended.)
RewriteRule (.*)/(.*)/(.*)\.html$ https://note.mathpro.id/$2.php?name=$3 [L,R=302]
This should not be an external redirect, it should be an internal rewrite. In order words, you want the (visible) URL to remain as /category/uncategorized.html. You don't want the end user to see /category.php?name=uncategorized.
For some reason you also have three capturing subpatterns in the RewriteRule pattern (.*)/(.*)/(.*)\.html$, whereas your example URL /category/uncategorized.html only has two?
Your regex should also be more restrictive. The "problem" with the very generic .* is that it is "greedy" and consumes everything, including slashes. So this regex will also match /foo/bar/baz/zip/bah/yop.html. (But which parts will it match/capture exactly?)
Try the following instead:
# 1. Canonical redirect (UNCHANGED)
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule (.*) https://example.com/$1 [L,R=301]
# 2. Rewrite to handler
RewriteRule ^([^/]+)/([^/]+)\.html$ $1.php?name=$2 [L]
This assumes the .htaccess file is located in the document root.
However, a minor problem with the above rewrite is that it rewrites the URL regardless of whether the "handler" (eg. category.php) exists or not. This isn't necessarily a big deal, but it means the 404 is triggered on category.php (the rewritten file-path), not /category/uncategorized.html (the originally requested URL from the user).
To resolve this, you can check whether the target file exists first. For example:
# 2. Rewrite to handler if it exists
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^/]+)/([^/]+)\.html$ $1.php?name=$2 [L]

htaccess http to https for domain and domain/paths

I need to convert all http access to a domain including its potential pages under the main page, to its https equivalent. What I have now just directs all Domain and www.Domain access to https://Domain but not pages that are off the main page. How can I modify the htaccess commands so in addition I can get http://Domain/other-web-pages to go to https://Domain/other-web-pages
RewriteEngine On
RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteRule (.*) https://example.com [L,R=301]
You are close. The redirection works, but you need to actually hand over the requested path too:
RewriteEngine On
RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteRule ^ https://example.com%{REQUEST_URI} [QSA,L,R=301]
Such general should get implemented in the actual http server's central host configuration. If you have no access to that you can use a distributed configuration file instaed. Such file has to be placed inside the http server's DOCUMENT_ROOT folder.
(An alternative to #arkascha's answer, that builds on your existing code.)
:
RewriteRule (.*) https://example.com [L,R=301]
You are already capturing the requested URL-path (ie. (.*)) but not passing this through to the substitution string. So, all you need is the corresponding backreference ($1) that contains the URL-path. For example:
:
RewriteRule (.*) https://example.com/$1 [L,R=301]
And, if you have other directives, this needs to go near the top of the .htaccess file before any existing rewrites.
You will need to clear your browser cache before testing, since any erroneous 301 (permanent) redirects to the homepage will have been cached by the browser. Test with 302 (temporary) redirects to avoid such caching issues.

htaccess changing automaticly the RewriteRule

I am trying to fix this error I had after adding these rules for HTTPS and non-www to .htaccess file on top
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301,QSA]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule (.*) https://www.%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301,QSA]
it did fix the HTTPS and non-www but it messed this rule
RewriteRule ^product/([0-9]+)$ product.php?p=$1 [NC,L,QSA]
it's now changing this URL whenever there is no HTTPS or no www
from : www.example.com/product/2443
to : www.example.com/product.php/2443?p=2443
I want it to go back to this again:
www.example.com/product/2443
It sounds like you've put the directives in the wrong order. Your canonical redirects (HTTP to HTTPS and non-www to www) need to be at the top of the .htaccess file before your internal rewrites.
Also, since you are internally rewriting to a file with the same basename as the requested URL-path you will need to make sure that MultiViews is disabled to prevent mod_negotiation from internally issuing a subrequest for /product.php/2443 before mod_rewrite is able to process the request. For example, at the top of your .htaccess file add the following to ensure that MultiViews is disabled:
Options -MultiViews
You will need to clear your browser cache, since these erroneous (301 - permanent) redirects will have been cached by the browser.
Aside:
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301,QSA]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule (.*) https://www.%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301,QSA]
Reverse these two rules to avoid a double redirect when requesting HTTP + non-www. However, you should leave these as they are if you are planning to implement HSTS.
The QSA flag is not required on either of these rules.
And the capturing RewriteRule pattern (ie. (.*)) is superfluous. It would be more efficient to just use ^ (or $) - an assertion - since it only needs to be successful for everything, it doesn't need to actually match anything.

.htaccess applies only to root, while I need it to work across the domain name

I have the following ReWrite Rule
RewriteCond %{REQUEST_URI} !/maintenance.php$ [NC]
RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif) [NC]
RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif) [NC]
RewriteCond %{REMOTE_ADDR} !{developer_ip}
RewriteRule .* /maintenance.php [R=302,L]
This .htaccess should redirect all requests to the maintenance.php, except the requests coming from {developer_ip} which is my own ip address.
Problem:
The above rules work, but when I click on any of the internal links, it again shows me maintenance.php (which due to the IP rule, must not happen) which ends in either a index.php?{some_query} or a URL which is also already rewritten by the .htaccess itself, such as /Page/About-US (which originally is index.php?page_id=200.
Now I want the .htaccess to redirect all requests to maintenace.php (which already is doing) but no the requests coming from {developer_ip}. The above rules are fine, except the part excluding my own ip address, which redirects me for the internal links.
Perform an internal rewrite to maintenance page and keep your rules in this order:
RewriteEngine On
RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif)$ [NC]
RewriteCond %{REMOTE_ADDR} !{developer_ip}
RewriteRule !^maintenance\.php$ /maintenance.php [NC,L]
# skip any requests alredy rewritten to maintenance.php
RewriteRule ^maintenance\.php$ - [NC,L]
# rest of your rewrite rules

RewriteCond for a folder only on a specific domain extension

I have a site that can be accessed via 3 domains (domain.com, domain.ch, domain.fr). The three use exactly the same files and folder, though.
Regarding the .fr domain (and only this domain), I need the following:
redirect domain.fr (root) to domain.com/fr/france.
This has been achieved with the following rule:
RewriteCond %{HTTP_HOST} ^www\.domain\.fr$
RewriteRule ^/?$ "http\:\/\/www\.domain\.com\/fr\/france" [R=301,L]
It works. (There's also a functioning rule to force www. in front of every URL.)
What I can't get to work is:
redirect domain.fr/fr also to domain.com/fr/france.
and finally, redirect any URL domain.fr/fr/* to domain.com/fr/*
(keeping whatever * stands for).
The trick (to me) is that the same .htaccess file will also be present on domain.com and domain.ch, but those rules must not activate for those domains.
You can put these rules in your htaccess
# Redirect [www.]domain.fr and [www.]domain.fr/fr to www.domain.com/fr/france
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.fr$ [NC]
RewriteRule ^(|fr)$ http://www.domain.com/fr/france [R=301,L]
# Redirect domain.fr/fr/* to domain.com/fr/*
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.fr$ [NC]
RewriteRule ^fr/(.*)$ http://www.domain.com/fr/$1 [R=301,L]
Try :
RewriteCond %{HTTP_HOST} ^www\.domain\.fr$
RewriteCond %{REQUEST_URI} !^/fr/france
RewriteRule ^fr/(.*)$ http://www.domain.com/fr/france/$1 [R=301,L]