.htaccess redirect loop when trying to add forced HTTPS rule (Amazon Elastic Beanstalk) - apache

I started receiving this error after trying to incorporate a rule to force HTTPS in the production environment. The BWC_ENV environment variable can have a handful of different values: "prod", "stage", "ben_local", "nam_local", etc.
Here's my .htaccess:
RewriteEngine On
# Force HTTPS
RewriteCond %{HTTPS} !=on
RewriteCond %{ENV:BWC_ENV} ^prod$
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Parse the subdomain as a variable we can access in our scripts
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{HTTP_HOST} !^www
RewriteCond %{HTTP_HOST} ^([^\.]+)\.([^\.]+)\.([^\.]+)$
RewriteRule ^(.*)$ /$1?subdomain=%1
# Ditto for the path; map all requests to /index.php
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !robots.txt
RewriteRule ^(.*)$ /index.php?path=$1 [L,QSA]
# robots.txt - supply the correct one for each environment
RewriteRule ^robots.txt$ /robots.prod.txt [NC]
RewriteCond %{ENV:BWC_ENV} !prod
RewriteRule ^robots.prod.txt$ /robots.stage.txt [NC]
Edit
What's more, if my .htaccess only contains the following, this will cause a redirect loop too. Why could this be?
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

It turns out this is an Amazon Elastic Load Balancer thing. You have to use Amazon's X-Forwarded-Proto header to accomplish this:
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule !/status https://%{SERVER_NAME}%{REQUEST_URI} [L,R]

You have L flag missing in few rules. Type changing your code to this:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# Force HTTPS
RewriteCond %{HTTPS} !=on
RewriteCond %{ENV:BWC_ENV} ^prod$
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Parse the subdomain as a variable we can access in our scripts
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{QUERY_STRING} !^$
RewriteCond %{HTTP_HOST} !^www
RewriteCond %{HTTP_HOST} ^([^.]+)\.[^.]+\.[^.]+$
RewriteRule ^(.*)$ /$1?subdomain=%1 [L,QSA]
# Ditto for the path; map all requests to /index.php
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !robots.txt
RewriteRule ^(.*)$ /index.php?path=$1 [L,QSA]
# robots.txt - supply the correct one for each environment
RewriteRule ^robots.txt$ /robots.prod.txt [L,NC]
RewriteCond %{ENV:BWC_ENV} !prod
RewriteRule ^robots.prod.txt$ /robots.stage.txt [NC,L]

Related

.htaccess configuration for https redirect and client routing

I have Apache 2.4.27 and two problems:
1. redirect http -> https
2. SPA (Vue2) client routing without #
Solution for 1(it works):
RewriteEngine on
RewriteCond %{HTTP_HOST} ^site\.com [NC]
RewriteCond %{HTTP:X-Forwarded-Proto} ^http$
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Solution for 2(Vue official recomendation):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
how to satisfy both conditions?
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^yoursite\.domen [NC]
RewriteCond %{HTTP:X-Forwarded-Proto} ^http$
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST} [R=301,L]
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
simple: solution1 + solution2 = it works

Force HTTPS on all pages except one

I have a WordPress site that I want fully secured using SSL, with the exception of one page (it has a third party script who will not serve over SSL - let's say it's called /booking/), I also want all URL's redirected to the www version.
I've seen similar answers for the other way around, but not this specific use case.
Is this achievable using .htaccess?
Edit:
Here is my .htaccess file:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
# BEGIN Custom
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_HOST} ^00\.00\.00\.00
RewriteRule (.*) https://www.mysite.co.uk/$1 [R=301,L]
RewriteCond %{HTTP_HOST} !^www\. [OR]
RewriteCond %{HTTPS} off
RewriteRule ^((?!online-booking).*) https://www.mysite.co.uk/$1 [NC,L,R,NE]
</IfModule>
# END Custom
*real IP replaced with zeros, this is to redirect the server IP to the actual website.
This code is for the page being at mysite.co.uk/online-booking/
Have it this way:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^00\.00\.00\.00
RewriteRule ^ https://www.mysite.co.uk%{REQUEST_URI} [R=301,L,NE]
RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} /online-booking [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ http://www.%1%{REQUEST_URI} [L,R=302,NE]
RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} !/online-booking [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [L,R=302,NE]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=302,NE]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
And make sure to test it after clearing your browser cache.
This should work :
RewriteEngine on
#--Redirect non-www or http requests excluding "/booking" to https--#
RewriteCond %{HTTP_HOST} !^www\. [OR]
RewriteCond %{HTTPS} off
RewriteRule ^((?!booking).*) https://www.example.com/$1 [NC,L,R,NE]

Redirecting HTTP to HTTPS correctly in Question2Answer script

I have searched for this question for many days and tried so many different methods but nothing works so far. I am using the Question2Answer script and I want to redirect all the HTTP requests to HTTPS.
My URL structure is set to :
/123/why-do-birds-sing (requires htaccess file)
and the htaccess file is as follow:
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php?qa-rewrite=$0&%{QUERY_STRING} [L]
RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"'
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]
</IfModule>
This correctly redirects http://example.com to https://example.com. However, if the user enters an address like this : www.example.com/users they are redirected to https://example.com/index.php?qa-rewrite=users which returns a 404 error.
The index.php?qa-rewrite= is added automatically and removing it from the htaccess totally messes up everything and I think it should be there.
This is because you need all of your redirect rules before any of the routing rules (the ones without the R flag), so:
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]
RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"'
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php?qa-rewrite=$0&%{QUERY_STRING} [L]
</IfModule>
I use this:
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-SSL} !on
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteRule ^(.*)$ "https\:\/\/example\.com\/$1" [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php?qa-rewrite=$0&%{QUERY_STRING} [L]
</IfModule>
If you don't like to redirect www, you can remove the line
RewriteCond %{HTTP_HOST} ^www\.example\.com$ and the [OR] above

Remove www as well as add https to a domain name

I'm looking to do the following rewrites:
http://website.com > https://website.com
www.website.com > https://website.com
https://www.website.com > https://website.com
Basically remove www of every combo and redirect everything to https.
Below is the current .htaccess config which seems to solve the first and second one above kind of well but falls apart on the 3rd one. Unable to see what's missing here.
<IfModule mod_rewrite.c>
RewriteEngine On
# remove www if it has it
RewriteCond %{HTTP_HOST} ^www\.
RewriteRule ^(.*)$ http://website.com/$1 [L,R,QSA]
# send everything to https
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-SSL} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# BEGIN WordPress
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
</IfModule>
Actually this can be done in a single rule itself:
RewriteEngine On
RewriteBase /
# remove www if it has it
RewriteCond %{HTTP_HOST} ^www\. [NC,OR]
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP:X-Forwarded-SSL} !on
RewriteRule ^ https://website.com%{REQUEST_URI} [L,R=302,NE]
# BEGIN WordPress
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress

Force HTTPS on certain URLs and force HTTP for all others

I have a client project where I need to force HTTPS for a certain folder and force HTTP for all others. I can sucessfully enforce HTTPS for the folder I desire but then all links back to the rest of the site end up being through HTTPS. I'd like to have a rule which forces requests for anything 'not' in the secure folder to be forced back to HTTP. Here's what I have so far:
RewriteEngine On
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{HTTPS} !=on
RewriteRule ^(my) https://%{HTTP_HOST}%{REQUEST_URI} [NC,R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1
'my' is the name of the folder that I need to force HTTPS for.
Any ideas?
Update: I also tried:
RewriteEngine On
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
# Force HTTPS for /my
RewriteCond %{HTTPS} !=on
RewriteRule ^(my) https://%{HTTP_HOST}%{REQUEST_URI} [NC,R=301,L]
# Force HTTP for anything which isn't /my
RewriteCond %{HTTPS} =on
RewriteRule !^my http://%{HTTP_HOST}%{REQUEST_URI} [NC,R=301,L]
# Remove index.php from URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1
But instead of requests for /my being forced through HTTPS they now just resolve to http://www.example.com/index.php/my
:?
Ah, of course. The problem lies in the fact that your rewrite ruleset will be reprocessed after it is transformed to index.php following the initial redirect. Using what you currently have, you need to additionally condition the redirections to make sure they don't get applied after the rewrite to /index.php/my.
Something like the following should do:
RewriteEngine On
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
# Force HTTPS for /my
RewriteCond %{HTTPS} !=on
RewriteCond %{THE_REQUEST} ^[A-Z]+\s/my [NC]
RewriteRule ^(my) https://%{HTTP_HOST}%{REQUEST_URI} [NC,R=301,L]
# Force HTTP for anything which isn't /my
RewriteCond %{HTTPS} =on
RewriteCond %{THE_REQUEST} !^[A-Z]+\s/my [NC]
RewriteRule !^my http://%{HTTP_HOST}%{REQUEST_URI} [NC,R=301,L]
# Remove index.php from URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1
Give the following a try, should work for you:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/my
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^/my
RewriteRule ^(.*)$ http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
This is something that works from an old client website and could be adaptable for your purposes:
#If https off and in the cart dir
RewriteCond %{HTTPS} =off [NC]
RewriteCond %{REQUEST_URI} ^/cart/(.*) [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}/cart/%1 [R=301,L]
#If https on and not in cart dir
RewriteCond %{HTTPS} =on
RewriteCond %{REQUEST_URI} !^/cart [NC]
#Above line actually used to read RewriteCond %{REQUEST_URI} !^/cart|media|images|thumbs|css|js [NC]
#to allow js/css/images to be served so there were no mixed ssl messages popping up to visitors
RewriteCond %{REQUEST_FILENAME} !index\.php$ [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
Replacing cart with my perhaps
Just invert the conditions:
RewriteCond %{HTTPS} =on
RewriteRule !^my http://%{HTTP_HOST}%{REQUEST_URI} [NC,R=301,L]