https to http while keeping path - .htaccess

I have here a little problem with a website and its WordPress blog.
For a short time, we had setup everything with https, until we were facing some issues and had to go back to HTTP.
Back then, I had a little collection of .htaccess files to deal with these kinds of problems, but I never actually tried my "non-www to www - ssl"
The intent was to add www and redirect https to http
RewriteCond %{HTTPS} on
RewriteRule ^/?$ http://%{SERVER_NAME}/ [R=301,L]
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Seemed pretty simple to me and I thought it should work.
I have two .htaccess files, one for http://www.example.com/ and one for http://www.example.com/blog both with the same content, as users are primarily coming from SE's via Blog.
The Problem is: If I load https://www.example.com/blog I get redirected to http://www.example.com/ instead of http://www.example.com/blog.
While writing the Question I thought I try this Question I had the idea to add this
RewriteCond %{HTTPS} on
RewriteRule ^/?$ http://%{SERVER_NAME}/{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
but then I get only redirected to http://www.example.com/{REQUEST_URI}
Could someone please tell me how I can keep the path on that redirect query?

RewriteCond %{HTTPS} on
RewriteRule ^/?$ http://%{SERVER_NAME}/{REQUEST_URI} [R=301,L]
If you notice that in your other directive you have %{REQUEST_URI}. You are missing the % prefix above. This is required syntax in order to get the value of the REQUEST_URI server variable. But also note that the value of REQUEST_URI already includes a slash prefix, so the slash should be omitted from the substitution. ie. instead of /{REQUEST_URI} it should be %{REQUEST_URI}.
Also note that the RewriteRule pattern (^/?$) only matches the root of your site (or /blog subdirectory if this .htaccess file is in that subdirectory). You need to match everything. So, modify the above RewriteRule like this:
RewriteRule ^ http://www.example.com%{REQUEST_URI} [R=301,L]
I've also hardcoded the domain, otherwise, you'll end up with a double redirect when requesting the non-canonical (ie. non-www) host.

Related

Rewrite subdomain to existing folders

I have a folder structure like this:
public_html
...images
...v2020
...v2021
With mod_rewrite, I redirect to the folder v2021 and force to https://www.example.com. Now I struggle with adding subdomains. When I go to images.example.com I want the redirection to the folder images, with images.example.com being unchanged in the address field.
I tested the code in two parts separately, first is the forwarding towards https://www including subdomain. It works without subdomains, but if I add any subdomain it leads to nowhere.
RewriteEngine on
# "example.com" to "www.example.com" (and HTTPS)
RewriteCond %{HTTP_HOST} ^(example\.com) [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,R=301,L]
# HTTP to HTTPS (same host) - preserve subdomain
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301,L]
The second part as a minimal working example is the forwording of the standard domain (no subdomain) and subdomain forwarding to a debug script.
RewriteCond %{HTTP_HOST} ^www\.example\.com
RewriteRule ^((?!v2021/).*)$ v2021/$1 [L]
RewriteCond %{HTTP_HOST} ^(.+?)\.example\.com
RewriteRule (.*) echo.php\?a=%1\&b=$1 [L]
The script works fine and outputs a="www" when using it with the upper condition, but it is not execute with the lower one. I get forwarded to nowhere.
Thanks for your help!
There seem to be several issues here...
RewriteCond %{HTTP_HOST} !^www\. [OR,NC]
RewriteCond %{HTTPS} off
RewriteRule ^ https://www.example.com%{REQUEST_URI} [NE,R=301,L]
You first rule redirects all your subdomains (every hostname that does not start www.) to www.example.com, so the subdomain is lost. You probably need to change the first condition so that it only redirects requests for example.com (the domain apex) to www.example.com. But you also need to split the HTTP to HTTPS redirect in order to preserve the subdomain (images etc.)
For example:
# "example.com" to "www.example.com" (and HTTPS)
RewriteCond %{HTTP_HOST} ^(example\.com) [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,R=301,L]
# HTTP to HTTPS (same host) - preserve subdomain
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301,L]
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule ^(.*)$ %1/$1 [L,NC,QSA]
This will result in an internal rewrite loop (500 error) since it repeatedly rewrites to subdomain/url-path resulting in subdomain/subdomain/subdomain/url-path etc. etc.
You need a condition to either only rewrite the direct/initial request (not rewritten requests), or check that the subdomain has not already been rewritten to a subdirectory of the same name.
However, this also rewrites the www subdomain, which I assume is not the intention, so another condition is required to exclude this.
For example, to only rewrite the initial request and exclude the www subdomain:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule (.*) %1/$1 [L]
By always rewriting the initial request and not explicitly checking that the subdirectory does not match the subdomain means that you can have a sub-subdirectory of the same name as the subdomain (if required). eg. /images/images/foo.jpg is not a problem.
The NC and QSA flags on the RewriteRule are not required. (Since it's already case-insensitive and you have no query string to append to.)
The REDIRECT_STATUS environment variable is empty on the initial request and set to 200 (as in 200 OK status) after the first successful rewrite, so by checking that it is empty it avoids a rewrite loop.
If you've configured a wildcard subdomain then you might want to check that the subdirectory exists before rewriting. (Although filesystem checks are relatively expensive, so this is probably best avoided if possible. Particularly when serving assets.)
RewriteRule ^((?!v2021/).*)$ /v2021/$1 [L]
This would seem to conflict with the above rule. Shouldn't this only apply to the www subdomain (the opposite of the above rewrite)? For example:
RewriteCond %{HTTP_HOST} ^www\.
RewriteRule ^((?!v2021/).*)$ v2021/$1 [L]

Redirect http to https and www to non-www in .htaccess

First of all, I know there are lots of answers on this, but I don't actually find one that works. This is what I have in the .htaccess file right now, and I want to mention that it worked previously, but it does not anymore.
Redirect 301 /unt-de-cacao-de-plaja/filtre/producator/crisnatur/ /ingrijire-corporala/unt-cacao/unt-de-cacao-pentru-plaja-100g
Options +FollowSymlinks
# Prevent Directoy listing
Options -Indexes
# Prevent Direct Access to files
<FilesMatch "(?i)((\.tpl|\.ini|\.log|(?<!robots)\.txt))">
Require all denied
## For apache 2.2 and older, replace "Require all denied" with these two lines :
# Order deny,allow
# Deny from all
</FilesMatch>
# SEO URL Settings
RewriteEngine On
# If your opencart installation does not run on the main web folder make sure you folder it does run in ie. / becomes /shop/
RewriteBase /
RewriteRule ^sitemap.xml$ index.php?route=extension/feed/google_sitemap [L]
RewriteRule ^googlebase.xml$ index.php?route=extension/feed/google_base [L]
RewriteRule ^system/download/(.*) index.php?route=error/not_found [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|js|css)
RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]
# FORCE HTTPS AND NON WWW
RewriteEngine on
RewriteCond %{ENV:HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
As a mention, I will have a lot of Redirect 301 from old pages to the new ones since the entire structure has been changed.
And the links that I am redirecting inside my website come with "www" like:
https://www.example.com/unt-de-cacao-de-plaja/filtre/producator/crisnatur/
and needs to be redirected to:
https://example.com/ingrijire-corporala/unt-cacao/unt-de-cacao-pentru-plaja-100g
Redirect to https and non-www
To instead redirect all requests to https and non-www, use the following code instead of the previous:
Canonical HTTPS/non-WWW
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule (.*) https://example.com/$1 [L,R=301]
</IfModule>
As before, place this code in the root .htaccess of your site. Here is what it's doing:
Checks if mod_rewrite is available
Checks if HTTPS is off, or if the request includes www
If either condition matches, the request qualifies and is redirected
to the https/non-www address
OR
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
A few issues, in order of importance:
You have your canonical HTTP to HTTPS and www to non-www redirects at the end of the file. By placing it at the end of the file, after your front-controller, it's simply never going to be processed for most requests. This needs to be near the start of the .htaccess file, before your front-controller.
You should avoid mixing redirects from both mod_alias (Redirect) and mod_rewrite (RewriteRule) in the same scope. Different modules execute at different times throughout the request, despite their apparent order in the config file. Since mod_rewrite is required for other redirects, you should convert the mod_alias Redirect directives to use RewriteRule instead.
For example:
RewriteRule ^unt-de-cacao-de-plaja/filtre/producator/crisnatur/$ /ingrijire-corporala/unt-cacao/unt-de-cacao-pentru-plaja-100g [R=301,L]
You should include the canonical scheme and hostname in your URL redirects in order to avoid multiple redirects when requesting an "old" URL at a non-canonical scheme ot hostname.
For example:
RewriteRule ^unt-de-cacao-de-plaja/filtre/producator/crisnatur/$ https://example.com/ingrijire-corporala/unt-cacao/unt-de-cacao-pentru-plaja-100g [R=301,L]
Depending on what you mean exactly by "a lot of Redirect 301" - you should not be doing this at all in .htaccess and instead redirecting in your server-side script, once you have determined that the request will 404. This is to prioritise normal site visiters and not your redirects (that get executed on every single request).
RewriteCond %{ENV:HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
Since you stated that these directives worked previously then I assume the use of the HTTPS environment variable is OK on your system. But note that, whilst this is relatively common, it's non-standard. (It implies the server is using some kind of SSL front-end/proxy.)
Note that the order of these rules will result in a double redirect when requesting http://www.example.com/<anything> (HTTP + www). Which is necessary if you are implementing HSTS, but otherwise, you should reverse these two rules to avoid this unnecessary double redirect.

redirect all external requests to the prod equivalent of the server url .htaccess

I'm trying to say:
For all IP Addresses that are not within the 110.140 or 110.10 ranges. If they are trying to access a URL that begins with "stage." then redirect them to the same URL but remove the "stage." portion of the string from the url.
RewriteCond %{REMOTE_ADDR} !^(110\.(140|10)) [NC]
RewriteCond %{HTTP_HOST} ^stage\. [NC]
RewriteRule stage\.(.*) https://$1 [R=301,L]
When using just the last two lines in made with love htaccess tester the last line fails (is not met). I haven't tested the code on a server.
Update:
After reading the Apache RewriteRule Directive details, I realized that the RewriteRule Directive does not search the HTTP_HOST, only the things after that. Therefore this approach will not work. Does anyone have an approach that will work?
Looks like your hostname starts with stage. not the URI. You may use this rule:
RewriteCond %{REMOTE_ADDR} !^110\.(140|10)
RewriteCond %{HTTP_HOST} ^stage\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L,NE]

Force HTTP for all pages except specific URLs

I have a situation where I need to force every single page in my site to redirect to HTTP except for two specific URLs which need to force redirect to HTTPS.
The two pages that need to redirect to HTTPS pages are:
/microsoft-moc-on-demand-video-training/moc-registration-page/
/courses/register/
The code I've been using in my .htaccess file looks like this:
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^/courses/register/
RewriteCond %{REQUEST_URI} !^/microsoft-moc-on-demand-video-training/moc-registration-page/
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule ^(/courses/register/|/microsoft-moc-on-demand-video-training/moc-registration-page/)/ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Unfortunately this doesn't seem to be working. The entire site does redirect to HTTP (so part of the code works), but those two exceptions (which should redirect to HTTPS) do not do that, they stay as HTTP links.
Any idea what I'm doing wrong here?
The problem is that for RewriteRule, there is no initial / in the requested path. Therefore, you're trying to match something that isn't present.
You also had an extra / at the end of each option in the first capture group, which when combined with the final / would require a path such as /courses/register//.
The following code should suit your needs:
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^/courses/register/
RewriteCond %{REQUEST_URI} !^/microsoft-moc-on-demand-video-training/moc-registration-page/
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule ^(courses/register|microsoft-moc-on-demand-video-training/moc-registration-page)/ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

.htaccess forcefully hide home page uri

I have the following .htaccess code:
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteRule ^$ subpage [L]
So basically if someone visit "www.example.com," he'll see the content of "www.example.com/subpage" without the url changed. This is good.
However, they can still visit the page by "www.example.com/subpage." If that happens, I want the url changed back to "www.example.com."
Is it possible? What I've tried so far gave me redirection loop.
You need an additional rule that matches against the actual request and not the URI. Since the rewrite engine loops, the URI keeps changing, so you need to match against the %{THE_REQUEST} variable. You need this rule before the rule that you have in your question:
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteCond %{THE_REQUEST} \ /+subpage(\?|\ |$)
RewriteRule ^ / [L,R=301]

Resources