.htaccess redirect loop issue - apache

If I go to domain.com, site redirects to domain.com/en, which is expected. But then the last rule kicks in and throws it in a loop making my url look something like this:
http://domain.com/en/?lang=en&request=&site=basecamp&lang=en&request=&site=basecamp&lang=en&request=&site=basecamp&lang=en&request=&site=basecamp
.htaccess file
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} !/(content|images|css|js|fonts|pdfs)/
RewriteRule /([^.]+\.(jpe?g|gif|bmp|png|css|js|eot|svg|ttf|ico|pdf))$ /$1 [NC,R,L]
RewriteCond %{REQUEST_URI} !(content|images|css|js|fonts|pdfs)/.*
RewriteRule !^[a-z]{2}/ /en/ [NC,L,R]
RewriteCond %{REQUEST_URI} !/(init\.php|content|images|css|js|fonts|pdfs)/
RewriteRule ^([a-z]{2})/(.*)$ init.php?lang=$1&request=$2&site=basecamp[L,QSA]
Why is the htaccess file redirecting to /?GET_VARS instead of /init.php?GET_VARS ?
And how can I avoid this loop?

Try changing your last condition by removing the leading and trailing slashes. You've rewritten your URI to:
/init.php
But there's no trailing slash like there is in the condition that you've provided, so the rule gets applied again. It should look like:
RewriteCond %{REQUEST_URI} !(init\.php|content|images|css|js|fonts|pdfs)
Not sure why you insist on having the trailing slash at the end of your condition here:
# with this / here, it will never match init.php --------v
RewriteCond %{REQUEST_URI} !/(init\.php|content|images|css|js|fonts|pdfs)/
But you can solve it by just excluding init.php directly:
RewriteCond %{REQUEST_URI} !init.php
So, just so it's clear, your last set of conditions/rule will look like:
RewriteCond %{REQUEST_URI} !init.php
RewriteCond %{REQUEST_URI} !/(content|images|css|js|fonts|pdfs)/
RewriteRule ^([a-z]{2})/(.*)$ init.php?lang=$1&request=$2&site=basecamp [L,QSA]
Or worst case, just add this in the very beginning of your rules:
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
Which prevents any kind of rewrite engine looping altogether.

Related

.htaccess - remove everything after third slash in path

On my website, I only use 3 slashes in my URL path:
https://example.com/this/isatest/
Right now I use .htaccess which makes it possible (as a side effect) to add as many stuff on the URL as you like:
https://example.com/this/isatest/hipperdihopperdus/pizza/bacon/with/cheese
I'd like to automatically remove everything after "isatest" while keeping the trailing slash using .htaccess.
This is what my .htaccess currently looks like:
Options -Indexes
Options +FollowSymLinks
RewriteEngine on
# 301 Redirect all requests that don't contain a dot or trailing slash to
# include a trailing slash
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_URI} !\.
RewriteRule ^(.*) %{REQUEST_URI}/ [R=301,L]
RewriteCond %{THE_REQUEST} /index\.html [NC]
RewriteRule ^index\.html$ /? [R=301,L,NC]
RewriteRule ^listen/$ /console/ [NC,L]
# Rewrites urls in the form of /parent/child/
# but only rewrites if the requested URL is not a file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?page=$1 [L,QSA]
How can I achieve this?
As your first rule, after the RewriteEngine directive, you can do something like the following:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
This checks if there is anything else (the dot) after two path segments and a slash, and redirects to removed "anything else".
Note that this is a 302 (temporary) redirect. Only change this to a 301 (permanent) redirect - if that is the intention - once you have confirmed that it works OK. This is to avoid the browser caching erroneous redirects whilst testing.
UPDATE: It may be more efficient to simply avoid redirecting files that end in a recognised file extension. Or perhaps exclude known directory location(s) of your static resources. For example:
RewriteCond %{REQUEST_URI} !\.(css|js|jpg|png|gif)$ [NC]
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
OR,
RewriteCond %{REQUEST_URI} !^/static-resources/
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
You can add this rule just below RewriteEngine On line:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+/[^/]+/).+$ /$1 [R=301,L,NE]

Redirection is not working with mod_rewrite in htaccess

I need to redirect few URIs having query string like:
/pages/foo.bar?pageId=123456 to http://some.site/spam/egg/
/pages/foo.bar?pageId=45678 to http://another.site/spaming/egging/
I have this in my htaccess:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/pages/foo.bar$
RewriteCond %{QUERY_STRING} ^pageId=123456$
RewriteRule ^.*$ http://some.site/spam/egg/ [R=301,L]
RewriteCond %{REQUEST_URI} ^/pages/foo.bar$
RewriteCond %{QUERY_STRING} ^pageId=45678$
RewriteRule ^.*$ http://another.site/spaming/egging/ [R=301,L]
But its not working, showing 404. What am i doing wrong?
You need to move these 2 rules i.e. before all other rules just below RewriteEngine On line as other rules might be overriding this.
(Based on your comments) Your culprit rule is this rule:
RewriteRule . index.php [L]
Which is actually rewriting every request to index.php and changing value of REQUEST_URI variable to /index.php thus causing this condition to fail:
RewriteCond %{REQUEST_URI} ^/pages/foo.bar$
From your example, you get redirected to
http://some.site/spam/egg/?pageId=123456
http://another.site/spaming/egging/?pageId=45678
You can use your browser developer tools to see the redirection (in the Network tab).
Maybe the query strings in the redirected URL lead to a 404? You can add a ? at the end of your redirection to clear the query string:
RewriteCond %{REQUEST_URI} ^/pages/foo.bar$
RewriteCond %{QUERY_STRING} ^pageId=45678$
RewriteRule ^.*$ http://another.site/spaming/egging/? [R=301,L]

How avoid infinite loop when htaccess rewrites to a copy of same htaccess-file?

I have this htaccess file:
RewriteEngine On
RewriteCond %{HTTP_HOST} =test.example.com [NC]
RewriteRule ^((?!test/).*)$ test/$1 [L,NC]
And a completely identical copy of the same file in the "test" directory. So, of course, this leads to an infinite loop when the first file pass you to the second file running the rules again.
I have tried add the rule RewriteCond %{REQUEST_URI} !^test [L,NC] in hope that REQUEST_URI stood for the real path and not the new "alias". However, it didn't worked.
Is there any way to maybe check which directory we are in to use in a condition? Or any other solution to this problem? With the basis to keep the both file's codes identical.
If you're already in test directory there is no point to rewrite again to test directory using a relative path. It will be better to determine the RewriteBase dynamically and use absolute paths for rewriting:
RewriteEngine On
# generate BASE dir in env variable %{ENV:BASE}
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTP_HOST} =test.example.com [NC]
RewriteRule ^(.*)$ %{ENV:BASE}test/$1 [L,NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$ is used to prevent rewriting after first rewriting of the rule since %{ENV:REDIRECT_STATUS} becomes 200 after that.
Okay, weird, but I now got it to work - simply like this:
RewriteCond %{HTTP_HOST} =test.example.com [NC]
RewriteCond %{REQUEST_URI} !test [NC]
RewriteRule ^((?!test/).*)$ test/$1 [L,NC]
Edit: Seems like it only works for the startpage. On other pages, the beginning trailing slash of the path is being removed.

Mod rewrite htaccess - two variables in rewrite rule

I found this solution online:
RewriteEngine On
RewriteBase /test/
RewriteRule ^([^-]*)/$ index.php?page=$1
RewriteRule ^([^-]*)/([^-]*)/$ index.php?page=$1&link=$2 [L]
#dodaje slash na koncu
RewriteRule ^(([a-z0-9\-]+/)*[a-z0-9\-]+)$ $1/ [NC,R=301,L]
The first one RewriteRule works perfect, it returns me $_GET['page']=130. But when it comes to second one, it returns me $_GET['page']=index.php instead of $_GET['page']=130 and $_GET['link']=35. That finish with SQL error, because of numeric id of page.
Normal link looks like:
?page=136
?page=136&link=35
Rewrited one:
/136/ - works
/136/35/ - doesn't work, $_GET['page']=index.php
You can replace your current code by this one (your htaccess has to be in test folder, and it's the same for index.php)
RewriteEngine On
RewriteBase /test/
# add trailing slash if no trailing slash and not an existing file/folder
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+[^/])$ $1/ [R=301,L]
RewriteRule ^([^/]*)/([^/]*)/$ index.php?page=$1&link=$2 [L]
RewriteRule ^([^/]*)/$ index.php?page=$1 [L]
You can try these links
http://domain.com/test/136/35/ internally rewrites to index.php?page=136&link=35
http://domain.com/test/136/35 redirects to http://domain.com/test/136/35/
http://domain.com/test/136/ internally rewrites to index.php?page=136
http://domain.com/test/136 redirects to http://domain.com/test/136/

mod redirect rule

I just want to redirect the URL through the mod rewrite ruls. I have applied this rule excluding (R=301)
Example :
from http:///webapp/wcs/stores/servlet/en/marksandspencer to http:///en/marksandspencer
I am using this rules for the mod redirect rules.
RewriteEngine on
RewriteCond %{REQUEST_URI} !^(/)?$
RewriteCond %{REQUEST_URI} !^/webapp.*$
RewriteCond %{REQUEST_URI} !^/wcsstore.*$
RewriteRule ^/(.*)$ /webapp/wcs/stores/servlet/$1 [PT,NC,L,QSA]
RewriteRule ^/webapp/wcs/stores/servlet/(.*) /$1 [NE,L,QSA]
RewriteRule ^(/)?$ /webapp/wcs/stores/servlet/en/marksandspencer [PT,NC,L]
No idea what you're trying to do, but if you're using Apache 2.0 or higher, the leading slash is stripped off of URI's when matching is done within a RewriteRule. Also, you have a rule that looks like you're adding a /webapp/wcs/stores/servlet/ to the beginning of a URI, then the very next rule it looks like you are removing it. This will probably cause a loop.
Taking a wild guess at what you are trying to do, I think you need to add a condition to the 2nd rule, and remove the leading slashes:
# internally rewrite URI by appending "/webapp/wcs/stores/servlet/" to the front
RewriteCond %{REQUEST_URI} !^(/)?$
RewriteCond %{REQUEST_URI} !^/webapp.*$
RewriteCond %{REQUEST_URI} !^/wcsstore.*$
RewriteRule ^(.*)$ /webapp/wcs/stores/servlet/$1 [PT,NC,L,QSA]
# if a request is made with "/webapp/wcs/stores/servlet/" in it, redirect to a URI with it stripped
RewriteCond %{THE_REQUEST} ^(GET/POST)\ /webapp/wcs/stores/servlet/
RewriteRule ^webapp/wcs/stores/servlet/(.*) /$1 [R=301,L,QSA]
RewriteRule ^$ /webapp/wcs/stores/servlet/en/marksandspencer [PT,NC,L]