.htaccess redirect url excluding certain subdirectories - apache

I'm trying to redirect my WordPress multisite root site to another page, but I still want to be able to access /wp-admin, /wp-login and /wp-json.
When I go to the browser I want url.com to redirect to newurl.com UNLESS it has one of the above directories on the end.
This is what I've come up with but when I go to the browser and enter url.com it loads the page as usual. Where am I going wrong?
Note: The block at the bottom is where the redirect should be happening.
Options FollowSymlinks
RewriteEngine On
RewriteBase /
# Force SSL / HTTPS
# Note: X-Forwarded-Proto is required for AWS's Elastic Load Balancing.
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]
RewriteRule ^(.*\.php)$ $1 [L]
RewriteRule . index.php [L]
# This is the block that should redirect, but isn't.
RewriteCond %{HTTP_HOST} ^url\.com$ [NC]
RewriteCond %{REQUEST_URI} !^(/wp-admin$|/wp-login$|/wp-json$)
RewriteRule ^ http://newurl.com/ [R=301]

Your rule was working fine.
You did not see it because it was never reached due to its position in the htaccess.
Actually, you need to place your rule before the default-last rule, otherwise it won't never be executed.
Options FollowSymlinks
RewriteEngine On
RewriteBase /
# Force SSL / HTTPS
# Note: X-Forwarded-Proto is required for AWS's Elastic Load Balancing.
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]
# This is the block that should redirect, but isn't.
RewriteCond %{HTTP_HOST} ^url\.com$ [NC]
RewriteCond %{REQUEST_URI} !^(/wp-admin$|/wp-login$|/wp-json$)
RewriteRule ^ http://newurl.com/ [R=301]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]
RewriteRule ^(.*\.php)$ $1 [L]
RewriteRule . index.php [L]

This works just fine for me. I changed a few things on the condition and added, the L flag to make sure it stops when the rule is met. Make sure your .htaccess file is being read. You can verify your apache config file has AllowOverride All or it won't read your htaccess file.
Options -FollowSymlinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^url\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/(wp-admin|wp-login|wp-json)$
RewriteRule ^ http://newurl.com/ [R=301,L]

Related

Issue redirecting query string to path

I want to redirect a get query parameter to a path and maintain the ability to use the GET parameter in the code.
I struggle to find examples excluding the file extension so perhaps this is what is throwing me.
I have tried the below code but not getting expected results from it?
RewriteCond %{REQUEST_URI} ^/spares/$
RewriteCond %{QUERY_STRING} pid=([0-9]*)$
RewriteRule ^(.*)$ /spares/%1 [R=302,L]
For example:
mysite.com/spares/?pid=x
to
mysite.com/spares/x
EDIT:
Copy of .htaccess in /dev/ subdirectory.
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /dev/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /dev/index.php [L]
</IfModule>
RewriteEngine On
# To externally redirect with pid
RewriteCond %{THE_REQUEST} \s+spares/\?pid=(.*)\s [NC]
RewriteRule ^ /spares/%1 [R=301,L,NE]
# To internally rewrite to ?pid=
RewriteCond %{QUERY_STRING} pid=(.+)$
RewriteRule ^dev/spares/$ /dev/spares/?pid=%1 [NC,L]
# END WordPress
Try with:
RewriteEngine On
# To externally redirect with pid
RewriteCond %{THE_REQUEST} \s/+spares/\?pid=(.*)\s [NC]
RewriteRule ^ /spares/%1 [R=301,L,NE]
# To internally rewrite to ?pid=
RewriteCond %{QUERY_STRING} pid=(.+)$
RewriteRule ^spares/$ /spares/?pid=%1 [NC,L]

htaccess redirect all but three pages to https

I know this sounds like a duplicate but I have tried as many methods as I can find and I still have not gotten this to work. So please do not auto mark this as a duplicate.
I am trying to redirect all pages of http://www.domian.com to https://www.domain.com with the exception of three pages:/products/product1, /products/product2, /products/product3
I also want those pages to always direct to http since if an https page links to it via a relative link, it will naturally have the https already there.
Also in play is that this is an expression engine site where I am removing the index.php from the URI.
Current Htaccess, which results in those three pages still being https even I go to Http for those pages.
### secure .htaccess file
<Files .htaccess>
order allow,deny
deny from all
</Files>
### EE 404 page for missing pages
ErrorDocument 404 /index.php/site/404
###Block Access to directories with no index file
Options -Indexes
### Simple 404 for missing files
<FilesMatch "(\.jpe?g|gif|png|bmp|css|js|flv)$">
ErrorDocument 404 "File Not Found"
</FilesMatch>
### Although highly unlikely, your host may have +FollowSymLinks enabled at the root level, yet disallow its addition in .htaccess; in which case, adding +FollowSymLinks will break your setup (probably a 500 error), so just remove it, and your rules should work fine.
###Options +FollowSymlinks
RewriteEngine On
RewriteBase /
###Removes index.php from ExpressionEngine URLs
RewriteCond %{THE_REQUEST} ^GET
RewriteCond %{THE_REQUEST} ^[^/]*/index\.php [NC]
RewriteRule ^index\.php(.+) $1 [R=301,L]
### Add the www
RewriteCond %{HTTP_HOST} ^domain\.com
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=permanent,L]
###each option I try I replace in this block as a reference
RewriteCond %{SERVER_PORT} 80
RewriteCond %{HTTPS} !on
RewriteCond %{REQUEST_URI} !^/products/product3
RewriteCond %{REQUEST_URI} !^/products/product1
RewriteCond %{REQUEST_URI} !^/products/product2
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]
######
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
###
Also have tried this which results in the same as above:
RewriteCond %{HTTPS} !on
RewriteCond %{HTTP_HOST} !^(domain\.com/products/product1|domain\.com/products/product2|domain\.com/products/product2) [NC]
RewriteRule ^(.*)$ https://www.domain.com/$1 [R,L]
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^(domain\.com/products/product1|domain\.com/products/product2|domain\.com/products/product2) [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R,L]
Tried this alone just to see if would be able to navigate to http://www.domain.com/products/product1 and at least not have it rewrite, but it still rewrites to https
RewriteCond %{HTTPS} !on
RewriteCond %{REQUEST_URI} !/products/product1 [NC,OR]
RewriteCond %{REQUEST_URI} !/products/product2 [NC,OR]
RewriteCond %{REQUEST_URI} !/products/product3 [NC,OR]
RewriteRule ^(.*)$ https://www.domain.com/$1 [R,L]
Tried this as well, which again still writes those pages to https. Plus if I try to go to http , it rewrites to https and doesn't remove the index.php
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} !^/products/product3
RewriteCond %{REQUEST_URI} !^/products/product1
RewriteCond %{REQUEST_URI} !^/products/product2
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^/products/product3 http://www.domain.com/products/product3 [R=301,QSA,L,NE]
RewriteRule ^/products/product1 http://www.domain.com/products/product1 [R=301,QSA,L,NE]
RewriteRule ^/products/product2 http://www.domain.com/products/product2 [R=301,QSA,L,NE]
I have honestly tried about 10 -15 versions of all this above and still cannot get it. Including adding index.php? to the request_URI in case that it sees that as part of the request_URI before it's removed. I either end up with the page still rewriting to https or redirect loop land.
Am I missing something simple, is something in the wrong order? I'm just at a loss.
thanks for any help.
UPDATE:
Here's what I used to get it to work:
RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} (\s/products/product1|\s/products/product2|\s/products/product3) [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [R,L]
RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} !\s/products/product1 [NC]
RewriteCond %{THE_REQUEST} !\s/products/product2 [NC]
RewriteCond %{THE_REQUEST} !\s/products/product3 [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
Here's how we achieved this on a site with a webcam that was in an iframe that wouldn't work on SSL. This was also an ExpressionEngine site.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
#force www instead of non-www
RewriteCond %{HTTP_HOST} ^domain.co.uk
RewriteRule ^(.*)$ http://www.domain.co.uk/$1 [R=301,L]
# HTTP/HTTPS handling
# Force HTTP for webcam page only
RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} \s/webcam-page [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [R,L]
# Force HTTPS for all pages except webcam
RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} !\s/webcam-page [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
# Removes index.php from ExpressionEngine URLs
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?/$1 [L]
</IfModule>

Apache Redirect certain HTTPS requests to HTTP not working

Hi I have been working on this for a while and just know I am doing something stupid but just can not see it. What I want to do is to redirect certain pages so they are always shown using HTTPS and all other pages if they are requested through HTTPS they are redirected as HTTP.
I have done lots of searching around the issue and found accepted answers on Stackoverflow that just did not work for me. So here Is my .htaccess file.
RewriteCond %{HTTPS} on
RewriteCond ${REQUEST_URI} !(finance/enquiryForm)(.*)
RewriteCond ${REQUEST_URI} !(offerentry)(.*)
RewriteRule (.*) http://dev.staging.co.uk/$1 [L,R=301]
RewriteCond %{HTTPS} off
RewriteRule ^(finance/enquiryForm|offerentry)(.*) https://dev.staging.co.uk/$1 [L,R=301]
What is currently happening is that the pages that I want to redirect from https to http work fine but the pages I want to show as HTTPS get a redirect loop and fail. If I comment out the top section the HTTPS pages I do want redirect fine. So how do I get the redirect loop to stop?
EDIT
The full .htaccess file with the codeigniter etc stuff.
Options +FollowSymLinks
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
<Files .*>
Order Deny,Allow
Deny From All
</Files>
#RewriteCond %{HTTPS} on
#RewriteCond ${REQUEST_URI} !/(finance/enquiryForm|offerentry) [NC]
#RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=302,NE]
#RewriteCond %{HTTPS} off
#RewriteCond ${REQUEST_URI} /(finance/enquiryForm|offerentry) [NC]
#RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=302,NE]
# Protect application and system files from being viewed
RewriteRule ^(fuel/install/.+|fuel/crons/.+|fuel/data_backup/.+|fuel/codeigniter/.+|fuel/modules/.+|fuel/application/.+|\.$
# Remove trailing slashes
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_URI} !fuel/.*$
RewriteRule ^(.*)/$ $1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [L]
</IfModule>
Options -Indexes
Try these rules based on THE_REQUEST variable:
RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} !/(finance/enquiryForm|offerentry) [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=302,NE]
RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} /(finance/enquiryForm|offerentry) [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=302,NE]
Test them in Chrome dev tool and see what redirects are you getting.
Try with:
RewriteCond %{HTTPS} on
RewriteCond ${REQUEST_URI} !(finance/enquiryForm|offerentry)
RewriteRule (.*) http://dev.staging.co.uk/$1 [L,R=301]
RewriteCond %{HTTPS} off
RewriteRule (finance/enquiryForm|offerentry) https://dev.staging.co.uk%{REQUEST_URI} [NE,L,R=301]

How to force http:// in htaccess?

I currently have this in my htaccess file to force https on all pages on my sign in and sign up pages:
# Force https://
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond $1 ^(sign-in|sign-up) [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
I want to force http whenever the page is not sign in or sign up. How do I do that?
EDIT 1:
I actually need to do the following:
Force https:// for pages in sign-up and sign-in
Force http:// for pages not in sign-up and sign-in
Remove www
Remove index.php
The relevant part of my .htaccess has this:
#
# Force https:// or http://
#
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond $1 ^(sign-in|sign-up) [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
#RewriteCond %{HTTPS} on
#RewriteCond $1 !^(sign-in|sign-up) [NC]
#RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
#RewriteCond %{HTTPS} on
#RewriteCond %{REQUEST_URI} !^/(sign-in|sign-up)(/|$) [NC]
#RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
#
# Supress "www" at the beginning of URLs. Source: HTML5 Boilerplate
#
<IfModule mod_rewrite.c>
RewriteEngine On
#RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
</IfModule>
#
# Supress "index.php"
#
<IfModule mod_rewrite.c>
RewriteEngine On
# Removes index.php from ExpressionEngine URLs
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
Have your rules like this:
RewriteEngine On
# force HTTPS for sign-in|sign-up
RewriteCond %{HTTPS} off
RewriteRule ^(sign-in|sign-up)(/|$) https://%{HTTP_HOST}%{REQUEST_URI} [NC,L,R=301]
# force HTTP for NOT sign-in|sign-up
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^/(sign-in|sign-up)(/|$) [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
I have not implemented this kind of solution personally (I have tended to use the PHP solution, like the one above, for it's simplicity), but the following may be, at least, a good start.
RewriteEngine on
# Check for POST Submission
RewriteCond %{REQUEST_METHOD} !^POST$
# Forcing HTTPS
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{SERVER_PORT} 80
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_secure [OR]
RewriteCond %{REQUEST_URI} ^something_else_secure
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
# Forcing HTTP
RewriteCond %{HTTPS} =on [OR]
RewriteCond %{SERVER_PORT} 443
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_public [OR]
RewriteCond %{REQUEST_URI} ^something_else_public
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
You can use environment variables to track the states you need and then only issue one redirect if necessary.
The following block should do exactly what you want:
<IfModule mod_rewrite.c>
RewriteEngine On
# Define default protocol for all assets
RewriteRule ^ - [E=protocol:http,E=ssl:%{HTTPS}off]
# Define HTTPS targets, add more cond as required
RewriteCond $1 (sign-in|sign-up) [NC]
RewriteRule (.*) - [E=protocol:https,E=ssl:%{HTTPS}on]
# Rewrite host if necessary and redirect on correct protocol
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ %{ENV:protocol}://%1%{REQUEST_URI} [L,R=301]
# Protocol switch if necessary (host is already correct)
RewriteCond %{ENV:ssl} ^(onoff|offon)
RewriteCond %{REQUEST_URI} !\.(gif|jpe?g|png|css|js)$ [NC]
RewriteRule ^ %{ENV:protocol}://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Finally, process the internal redirect
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
In this configuration, the protocol environment variable is used to track the actual protocol name to use and the ssl environment variable is the test to check if we are already on the correct protocol for the URI.
Using environment variables gives you 2 advantages :
you avoid redirection chains. This configuration will redirect the user-agent at most once.
you're DRY (Don't repeat yourself). Each condition is only expressed once, so it's easier to maintain.

.htaccess ensure www redirect incorrect

I am trying to ensure that urls always have www in front of them for canonicalization reasons.
Unfortunately when I put the following url in:
http://website.net/handbags/1/12/this-is-some-text
It redirects me here:
http://www.website.net/?controller=handbags&path=1/12/this-is-some-text
I would like to add it works fine when using:
http://www.website.net/handbags/1/12/this-is-some-text
I want it to redirect me here...
http://www.website.net/handbags/1/12/this-is-some-text
I'm not sure what could be causing this error. Here is my .htaccess file:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# CORE REDIRECT
RewriteRule ^([a-zA-Z]*)/?(.*)?$ index.php?controller=$1&path=$2 [NC,L]
# ENSURE WWW
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^([^.]+\.[a-z]{2,6})$ [NC]
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
# ENSURE WWW
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^([^.]+\.[a-z]{7})$ [NC]
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]
# CORE REDIRECT
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z]*)/?(.*)?$ index.php?controller=$1&path=$2 [NC,L]
</IfModule>
You can do what I've done above; however, it's just going to redirect to http://www.website.net/handbags/1/12/this-is-some-text and then it's immediately going to hit the "CORE REDIRECT" rule and send you to http://www.website.net/?controller=handbags&path=1/12/this-is-some-text.
Is there a reason you don't want it to redirect to "?controller=handbags" when they go to www?
UPDATE
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
# ENSURE WWW
Rewritecond %{HTTP_HOST} !^www\.website\.net
RewriteRule ^(.*)$ http://www.website.net/$1 [R=301,L]
# CORE REDIRECT
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z]*)/?(.*)?$ index.php?controller=$1&path=$2 [NC,L]
</IfModule>
Whenever your # CORE REDIRECT matches, the other rules are not even checked, as the core redirect rule has the Lflag set. That ones tells Apache to stop trying other rules. Remove that flag or change the rule. ;)