.htaccess 301 redirect with exclusion does not work - apache

I try to use a simple 301 redirect
from domain1.com/folder/ to domain2.com/
but excluding domain1.com/folder/subfolder
I use the following code in .htaccess:
RedirectMatch 301 ^/folder/((?!subfolder).*)$ https://domain2.com/$1
but it simply redirects all the requests, including the requests to subfolder.
Please, help to fix the line to make it work as described. Thank you!
here is the complete code of .htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /folder/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /folder/index.php [L]
</IfModule>
RedirectMatch 301 ^/folder/((?!subfolder).*)$ https://domain2.com/$1

Try it like this using mod_rewrite instead:
(NB: This assumes the .htaccess file is located in the document root.)
# /.htaccess
# Redirect all direct requests, except "subfolder"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond $1 !^subfolder($|/)
RewriteRule ^folder/(.*) https://domain2.com/$1 [R=301,L]
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /folder/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /folder/index.php [L]
</IfModule>
It is important that the redirect goes before the rewrite to your front-controller.
You will need to ensure your browser cache is cleared before testing and test with a 302 (temporary) redirect to avoid potential caching issues.
UPDATE:
Yes, /folder has it's own .htaccess (this is the file I am working at all this time). Yes, /folder is where Wordpress is installed.
In that case you would need to change the above redirect to read as follows (it won't do anything otherwise):
# /folder/.htaccess
# Redirect all direct requests, except "subfolder"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond $1 !^subfolder($|/)
RewriteRule (.*) https://domain2.com/$1 [R=301,L]
Basically, you need to remove folder/ from the start of the regex that matches the URL-path. The URL-path that the RewriteRule pattern matches against is relative to the directory that contains the .htaccess file.
The addition of the check against the REDIRECT_STATUS env var is to ensure that rewritten requests to the WP front-controller (when subfolder is requested) are not redirected.
You can also "simplify" the WordPress directives that follow (although if these are enclosed in # BEGIN WordPress / # END WordPress comment markers then you should leave the directives as they are since they are maintained by WordPress). For example:
RewriteEngine On
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
The RewriteBase directive is not required. And neither is the <IfModule> wrapper. (But as I said above, only change this if you are hand-coding the .htaccess and not letting WordPress maintain it.)

Related

SEO URL and Rewrite Rule force on one domain

I have a rewrite rule to force user to go from example.com to www.example.com. This is for SEO reasons so that I have no duplicated websites and content on my Google results.
# BEGIN Spark
AddDefaultCharset UTF-8
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
</IfModule>
<IfModule mod_deflate.c>
<FilesMatch "\.(html|php|txt|xml|js|css|ttf|otf|ico|json|svg|)$">
SetOutputFilter DEFLATE
</FilesMatch>
</IfModule>
# END Spark
My question. If now people post a link example.com/news they always will redirect to the frontpage like www.example.com. How can I manage that they still can use and post short URLs like example.com/news1 or example.com/news2 and will redirect to www.example.com/news1 or www.example.com/news2 respectively.
You've put the rule in the wrong place. It needs to go before the internal rewrite (to the front-controller: index.php). eg. at the top of the file, not at the end.
By placing it last it will only correctly redirect physical directories (which includes the homepage) and static resources (images, CSS, JS, etc.). All other "short URLs" that are routed through the front-controller will be redirected to index.php and you'll see the "frontpage".
And... to avoid a double redirect when requesting example.com with a URL that contains a trailing slash then include an absolute URL in the trailing slash removal rule and include your non-www to www rule immediately after that.
For example:
RewriteEngine On
# Remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ https://www.example.com/$1 [L,R=301]
# Redirect non-www to www
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
# Front-controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
You will need to clear the browser cache before testing since the erroneous 301 (permanent) redirects will have been cached by the browser. (Test with 302 - temporary - redirects to avoid caching issues.)
Aside: An additional concern is that these directives are inside a # BEGIN Spark ... # END Spark code block - which makes it look as if these directives are perhaps maintained by some automated process? In which case, they might be overwritten?

Rewrite rule for opening a different page

I'm stuck with some .htaccess rules.
I've got the page /module/slug. I want, when I type slug to see content of /module/slug/ but not redirect to this page. Is it possible? I've tried this rule, but had no luck:
RewriteRule ^slug/$ /module/slug/ [L]
My .htaccess content:
# 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]
RewriteRule ^calculator/$ /sample-page/ [R=301,L]
</IfModule>
# END WordPress
That happens because you don't tell Apache to redirect (R=301).
Add the redirect flag R, and it should work. Also make sure that:
You have set the RewriteBase correctly.
There are not any other rules earlier in the file that match the same URL.
.
RewriteEngine On
RewriteBase /
RewriteRule ^slug/$ /module/slug/ [R=301,L]

How to prevent ReweiteRules to match subdomains

How can I limit my mod_rewrite RewriteRules to only apply to the www and no-subdomain?
The subdomains are in different folders -- rather website root folder, however all of my RewirteRules apply to all of the subdomains, which is not what I want.
I know that it's possible to match every RewriteRule by a RewriteCond that only matches www and no-subdomain, but then I have to repeat the same thing for all the RewriteRules, which is not what I want again.
So I was wondering if there is any way to globally prevent RewriteRules to apply to other subdomains? I can also place .htaccess files in each subdomain as well to prevent matching, if that's a possibility.
Here is part of what I have in .htaccess right now:
options -Indexes -MultiViews +FollowSymLinks
Header set Access-Control-Allow-Origin *
RewriteEngine On
RewriteBase /
RewriteRule ^city/([^/].+)/([^/].+)/([^/].+)/$ index.php?page=$3&city=$1 [L]
RewriteRule ^city/([^/].+)/([^/].+)/$ index.php?city=$1 [L]
RewriteRule ^flights/([^/].+)/$ index.php?page=flights&mode=$1 [L]
RewriteRule ^health/([^/].+)/$ index.php?page=health&view=$1 [L]
# so on ...
RewriteRule ^([^/].+)/$ index.php?page=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule . index.php [L]
Update #1
Just to explain the problem better, right now sub.domain.com shows domain.com instead of it's actual content.
You can insert this single rule below RewriteBase line to ignore all sub-domains from rest of the rules:
# ignore all sub domains
RewriteCond %{HTTP_HOST} !^(www\.)?example\.com$ [NC]
RewriteRule ^ - [L]
Replace example.com with your actual domain.

.htaccess parse url works on localhost but gets redirect loop on VPS host

I'm trying to parse urls with .htaccess and pull our either 1 or 2 parameters to load content based on the url.
If only the first url param (site.com/param1) is present then that's fine and should route to index.php?c=param but could also be (site.com/param1/param2) and get routed to index.php?c=param1&p=param2
It works perfectly on MAMP PRO running on Mavericks but when I clone the repo onto our VPS I get a redirect loop. There is an admin area for the site so I need to ignore the any url that follows the pattern
site.com/admin
The "parsable" urls follow this pattern
site.com/param1
or
site.com/param1/param2
The .htaccess looks like this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
## SEO REWRITES ###
RewriteRule ^(admin) - [L]
RewriteRule ^/?([a-zA-Z0-9_]+)/?$ /index.php?page=$1
RewriteRule ^/?([a-zA-Z0-9_]+)/([0-9]+)/?$ /index.php?page=$1&e=$2
## URL PARSE ##
RewriteRule ^([^/]+)$ /index.php?c=$1
RewriteRule ^([^/]+)/([^/]+)$ /index.php?c=$1&p=$2
</IfModule>
I'm lost but I feel like I'm missing something simple here. The most confusing part is that it has worked since development began. Anyone have any ideas as to why the redirect loop when running on an vps with apache but not on localhost or more importantly how to get it parsing on the live server.
Im now using this which works except when the trailing slash is missing from the url, then it breaks, Ive tried dif variations to let it match without a trailing slash but i just get 404's or internal server errors:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^(admin) - [L]
RewriteRule ^/?([a-zA-Z0-9_]+)/?$ /index.php?page=$1
RewriteRule ^/?([a-zA-Z0-9_]+)/([0-9]+)/?$ /index.php?page=$1&e=$2
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?([^/]+)/([^/]+)$ /index.php?c=$1&p=$2 [L,QSA]
RewriteRule ^/?([^/]+)/$ /index.php?c=$1&p=index [L,QSA]
</IfModule>
Have it this way:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
## SEO REWRITES ###
RewriteRule ^(admin) - [L]
RewriteRule ^/?(\w+)/([0-9]+)/?$ /index.php?page=$1&e=$2 [L,QSA]
RewriteRule ^/?(\w+)/?$ /index.php?page=$1 [L,QSA]
## URL PARSE ##
RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?c=$1&p=$2 [L,QSA]
RewriteRule ^([^/]+)/?$ /index.php?c=$1 [L,QSA]
</IfModule>
The problem is that
RewriteRule ^([^/]+)$ /index.php?c=$1
matches
index.php?c=blah
You need to add a rule so that any valid paths are served without modification.
Try adding
RewriteCond %{REQUEST_FILENAME} !-f
just after RewriteEngine on

htaccess remove index.php from url

I have a problem whereby google has indexed some pages with the wrong url.
The url they are indexing is:
http://www.example.com/index.php/section1/section2
I need it to redirect to:
http://www.example.com/section1/section2
.htaccess isn't my forte, so any help would be much appreciated.
The original answer is actually correct, but lacks explanation. I would like to add some explanations and modifications.
I suggest reading this short introduction https://httpd.apache.org/docs/2.4/rewrite/intro.html (15mins) and reference these 2 pages while reading.
https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
https://httpd.apache.org/docs/2.4/rewrite/flags.html
This is the basic rule to hide index.php from the URL. Put this in your root .htaccess file.
mod_rewrite must be enabled with PHP and this will work for the PHP version higher than 5.2.6.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.php/$1 [L]
Think %{REQUEST_FILENAME} as the the path after host.
E.g. https://www.example.com/index.html, %{REQUEST_FILENAME} is /index.html
So the last 3 lines means, if it's not a regular file !-f and not a directory !-d, then do the RewriteRule.
As for RewriteRule formats:
So RewriteRule (.*) /index.php/$1 [L] means, if the 2 RewriteCond are satisfied, it (.*) would match everything after the hostname. . matches any single character , .* matches any characters and (.*) makes this a variables can be references with $1, then replace with /index.php/$1. The final effect is to add a preceding index.php to the whole URL path.
E.g. for https://www.example.com/hello, it would produce, https://www.example.com/index.php/hello internally.
Another key problem is that this indeed solve the question. Internally, (I guess) it always need https://www.example.com/index.php/hello, but with rewriting, you could visit the site without index.php, apache adds that for you internally.
Btw, making an extra .htaccess file is not very recommended by the Apache doc.
Rewriting is typically configured in the main server configuration
setting (outside any <Directory> section) or inside <VirtualHost>
containers. This is the easiest way to do rewriting and is recommended
To remove index.php from the URL, and to redirect the visitor to the non-index.php version of the page:
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
This will cleanly redirect /index.php/myblog to simply /myblog.
Using a 301 redirect will preserve Google search engine rankings.
RewriteEngine On
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.php($|\ |\?)
RewriteRule ^ /%1 [R=301,L]
Assuming the existent url is
http://example.com/index.php/foo/bar
and we want to convert it into
http://example.com/foo/bar
You can use the following rule :
RewriteEngine on
#1) redirect the client from "/index.php/foo/bar" to "/foo/bar"
RewriteCond %{THE_REQUEST} /index\.php/(.+)\sHTTP [NC]
RewriteRule ^ /%1 [NE,L,R]
#2)internally map "/foo/bar" to "/index.php/foo/bar"
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ /index.php/$1 [L]
In the spep #1 we first match against the request string and capture everything after the /index.php/ and the captured value is saved in %1 var. We then send the browser to a new url.
The #2 processes the request internally. When the browser arrives at /foo/bar , #2rule rewrites the new url to the orignal location.
Steps to remove index.php from url for your wordpress website.
Check you should have mod_rewrite enabled at your server.
To check whether it's enabled or not - Create 1 file phpinfo.php at your root folder with below command.
<?php
phpinfo?();
?>
Now run this file - www.yoursite.com/phpinfo.php and it will show mod_rewrite at Load modules section.
If not enabled then perform below commands at your terminal.
sudo a2enmod rewrite
sudo service apache2 restart
Make sure your .htaccess is existing in your WordPress root folder, if not create one .htaccess file
Paste this code at your .htaccess file :-
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Further make permission of .htaccess to 666 so that it become writable and now you can do changes in your wordpress permalinks.
Now go to Settings -> permalinks -> and change to your needed url format.
Remove this code /index.php/%year%/%monthnum%/%day%/%postname%/
and insert this code on Custom Structure: /%postname%/
If still not succeeded then check your hosting, mine was digitalocean server, so I cleared it myself
Edited the file /etc/apache2/sites-enabled/000-default.conf
Added this line after DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride All
</Directory>
Restart your apache server
Note: /var/www/html will be your document root
Do the following steps
1. Make sure that the hosting / your pc mod_rewrite module is active. if not active then try to activate in a way, open the httpd.conf file. You can check this in the phpinfo.php to find out.
change this setting :
#LoadModule rewrite_module modules/mod_rewrite.so
to be and restart wamp
LoadModule rewrite_module modules/mod_rewrite.so
2. Then go to .htaccess file, and try to modify to be:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\?*$ index.php/$1 [L,QSA]
if above does not work try with this:
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
3. Move .htaccess file to root directory, where is index.php there.
www OR root folder
- index.php
- .htaccess
Some may get a 403 with the method listed above using mod_rewrite. Another solution to rewite index.php out is as follows:
<IfModule mod_rewrite.c>
RewriteEngine On
# Put your installation directory here:
RewriteBase /
# Do not enable rewriting for files or directories that exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
I have used many codes from the above mentioned sections for removing index.php form the base url. But it was not working from my end. So, you can use this code which I have used and its working properly.
If you really need to remove index.php from the base URL then just put this code in your htaccess.
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
This will work, use the following code in .htaccess file
RewriteEngine On
# Send would-be 404 requests to Craft
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]
I don't have to many bulky code to give out just a little snippet solved the issue for me.
i have https://example.com/entitlements/index.php rather i want anyone that types it to get error on request event if you type https://example.com/entitlements/index
you will still get error since there's this word "index" is contained there will always be an error thrown back though the content of index.php will still be displayed properly
cletus post on "https://stackoverflow.com/a/1055655/12192635" which
solved it
Edit your .htaccess file with the below
to redirect people visiting https://example.com/entitlements/index.php to 404 page
RewriteCond %{THE_REQUEST} \.php[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
to redirect people visiting https://example.com/entitlements/index to 404 page
RewriteCond %{THE_REQUEST} \index[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
Not withstanding we have already known that the above code works with already existing codes on stack see where i applied the code above just below the all codes at it end.
# The following will allow you to use URLs such as the following:
#
# example.com/anything
# example.com/anything/
#
# Which will actually serve files such as the following:
#
# example.com/anything.html
# example.com/anything.php
#
# But *only if they exist*, otherwise it will report the usual 404 error.
Options +FollowSymLinks
RewriteEngine On
# Remove trailing slashes.
# e.g. example.com/foo/ will redirect to example.com/foo
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=permanent,QSA]
# Redirect to HTML if it exists.
# e.g. example.com/foo will display the contents of example.com/foo.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+)$ $1.html [L,QSA]
# Redirect to PHP if it exists.
# e.g. example.com/foo will display the contents of example.com/foo.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php [L,QSA]
RewriteCond %{THE_REQUEST} \.php[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
RewriteCond %{THE_REQUEST} \index[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
try this, it work for me
<IfModule mod_rewrite.c>
# Enable Rewrite Engine
# ------------------------------
RewriteEngine On
RewriteBase /
# Redirect index.php Requests
# ------------------------------
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteCond %{THE_REQUEST} !/system/.*
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,L]
# Standard ExpressionEngine Rewrite
# ------------------------------
RewriteCond $1 !\.(css|js|gif|jpe?g|png) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
For more detail
create .htaccess file on project root directory and put below code for remove index.php
RewriteEngine on
RewriteCond $1 !^(index.php|resources|robots.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]