Rule exceptions in mod_rewrite - apache

I have created page that every new user is redirected to upon visit, it sets a cookie that allows access to the rest of my site. I want to add exception to this rule for some sites and their bots:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_REFERER} http://www.site1.com [NC,OR]
RewriteCond %{HTTP_REFERER} http://www.site2.net [NC,OR]
RewriteCond %{HTTP_USER_AGENT} bot1 [NC,OR]
RewriteCond %{HTTP_USER_AGENT} bot2 [NC]
RewriteRule .? - [S=1]
RewriteCond %{HTTP_COOKIE} !yes=1 [NC]
RewriteRule !^(script1.php|script2.php)$ script2.php [L]
</IfModule>
As you can see, if the cookie doesn't exist or !=1 every user is redirected to script2.php.
I wrote some exceptions, but sometimes it works, and sometimes it doesn't.
I've made an error somewhere, but i don't see it.
Can you help me with this? Thank you for you time.

I'd rather use [L] instead of [S=1].
Secondly, I would do a external redirect to script2.php, so it's not cached (incorrectly). So use [R,L] instead of just [L] on your last rule.

Related

.htaccess redirect facebook crawlers except privacy policy

I have a SPA app with dynamic content for sharing on Facebook so I am redirecting Facebook crawlers to a nice static page using the following rule in htaccess:
<IfModule mod_rewrite.c>
RewriteCond %{HTTP_USER_AGENT} ^facebookexternalhit.*$
RewriteRule ^(.*)$ https://sharing.mysite.tld/api/share/$1 [L]
This works great! But there is one problem... I can't make my app live because Facebook requires a link to privacy policy, terms and conditions etc - and these get redirected too!!
I need to ignore a certain URLs - anything requested in /docs/ - from the above rule EDIT: so that urls containing /docs/ are followed as normal (no redirect, just served normally). I can't get .htaccess to pick up on the ignore rule. I would have thought this would do it (with thanks to https://stackoverflow.com/a/1848579/4881971):
RewriteRule ^(docs)($|/) - [L]
so I would have thought my .htaccess file would look like this :
<IfModule mod_rewrite.c>
RewriteCond %{HTTP_USER_AGENT} ^facebookexternalhit.*$
RewriteRule ^(docs)($|/) - [L]
RewriteRule ^(.*)$ https://sharing.mysite.tld/api/share/$1 [L]
but when I use Facebook Object Debugger on https://mysite.tld/docs/privacy I get a 404! It redirecting to https://sharing.mysite.tld/api/share/docs/privacy
How do I retain the rule but ignore requests from mysite.tld/docs/* ? Thanks.
Could you please try following, please make sure you clear your browser cache before testing your URLs. This considers your uri starts from docs.
<IfModule mod_rewrite.c>
RewriteEngine ON
RewriteCond %{HTTP_USER_AGENT} ^facebookexternalhit.*$ [NC]
RewriteCond %{REQUEST_URI} ^/docs [NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)$ https://sharing.mysite.tld/api/share/$1 [L]
In case you want to pass URLs where docs could come anywhere in uri(not from starting what 1st solution looks for), then try following Rules.
<IfModule mod_rewrite.c>
RewriteEngine ON
RewriteCond %{HTTP_USER_AGENT} ^facebookexternalhit.*$ [NC]
RewriteCond %{REQUEST_URI} docs [NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)$ https://sharing.mysite.tld/api/share/$1 [L]
Have it like this with a negated comdition:
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} ^facebookexternalhit [NC]
RewriteRule %{THE_REQUEST} !\s/+docs [NC]
RewriteRule ^ https://sharing.mysite.tld/api/share%{REQUEST_URI} [L,R=301,NE]

Apache, url rewrite

I have the following .htaccess file inside my root directory:
RewriteEngine On
<If "%{SERVER_NAME} = 'example.com'">
# The actual condition is really long one so I replaced it for illustration.
RewriteCond %{HTTP_USER_AGENT} (iPhone|Blackberry|Android) [NC]
RewriteRule .* http://m.example.com%{REQUEST_URI} [R,L]
RewriteCond %{REQUEST_URI} ^/([a-z-]+)/$ [NC]
RewriteRule .* %{REQUEST_SCHEME}://%{SERVER_NAME}/?title=%1 [L]
</If>
<Else>
RewriteCond %{REQUEST_URI} ^/([a-z-]+)/$ [NC]
RewriteRule .* %{REQUEST_SCHEME}://%{SERVER_NAME}/?title=%1 [L]
DirectoryIndex /m/index.htm /m/index.php /m/index.html
</Else>
So as you can see its a pretty much simple way to redirect users of mobile devices to m.example.com and if that is the case I change the DirectoryIndex, few notes:
The reason I duplicate the same RewriteCond/RewriteRule is because I can't use them outside <If>/<Else> blocks.
The way I redirect(if/else) is not the question and I'm pretty sure not the best way, but if anyone have suggestions I'm all ears.
The problem:
If I access example.com/Article-Name on desktop browser there will be internal redirection to: example.com/?title=articleName but I won't see example.com/?title=articleName at my url bar as expected.
The exception:
If I access m.example.com/Article-Name my url bar is now m.example.com/?title=articleName.
I was expecting the same behavior as the desktop (internal redirection not redirection I can see on my url bar), I'm pretty sure its because the DirectoryIndex but I don't how to prove it or solve this issue, if anyone have a solution I will be very thankful.
The main issue with your code is that you're feeding it with an URL that is not the same as the current URL then, what happens is that it ignores the internal and make it an external redirect.
Another very important thing is that you forgot %{HTTP_USER_AGENT} to match against the mobile browsers.
Here is an idea to resolve your issue:
RewriteEngine On
# First we verify if its a mobile device and
# if its not already on the mobile subdomain
RewriteCond %{HTTP_HOST} !^m\.domain\.com$ [NC]
RewriteCond %{HTTP_USER_AGENT} (iPhone|Blackberry|Android) [NC]
RewriteRule ^ http://m.example.com%{REQUEST_URI} [R,L]
# here we deal with all the internal redirects for
# the mobile subdomain
RewriteRule ^m/index\.php$ - [L]
RewriteCond %{HTTP_HOST} ^m\.domain\.com$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ /m/index.php?title=$1 [L]
# here we deal with the normal website
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ /index.php?title=$1 [L]
Your doing internal redirects, if you want to redirect to a new URL use external ones
Replace [L] with [L,R=302]
or 301 if you want the result to be cached

Consolidating redundant RewriteCond lines in .htaccess

I'm trying to consolidate multiple RewriteCond lines in .htaccess and am struggling with the syntax. Here is my code for the redirect area of my .htaccess file:
RewriteEngine On
# BEGIN page-level mobile redirects
<IfModule mod_rewrite.c>
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteRule ^(index.html)?$ http://m.example.com [L,R=301]
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteRule ^page-1/$ http://m.example.com/p1 [L,R=301]
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteRule ^page-2/$ http://m.example.com/p2 [L,R=301]
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteRule ^page-3/$ http://m.example.com/p3 [L,R=301]
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteRule ^category/page-4/$ http://m.example.com/p4 [L,R=301]
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteRule ^category/page-5/$ http://m.example.com/p5 [L,R=301]
</IfModule>
# END mobile redirects
The above solution works properly but is inefficient because there are so many redundant ReWriteCond lines. My goal is to have a single RewriteCond line apply to all of my RewriteRule lines. Is this possible?
I'd normally use REQUEST_URI to more efficiently accomplish this, but i'm unable to in this instance because we're rewriting requests for multiple similar desktop web sites with varied URL layouts to a single mobile web site folder.
Read up on skip and last flags in the Apache documentation. You can also use the regexps to fold some of the lines:
# BEGIN page-level mobile redirects
<IfModule mod_rewrite.c>
RewriteCond %{HTTP_USER_AGENT} !"android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile"
RewriteRule ^ - [skip=3]
RewriteRule ^(index.html)?$ http://m.example.com [L,R=301]
RewriteRule ^page-([123])/$ http://m.example.com/p$1 [L,R=301]
RewriteRule ^category/page-([45])/$ http://m.example.com/p$1 [L,R=301]
</IfModule>
# END mobile redirects
BTW, It's a misconception to think of this in runtime terms. Yes, each regexp / rule will add 10s of μS, but the real hit in performance terms is the need to open and to read the .htaccess file, any .htaccess file in the first place. Do this sort of thing for clarity and ease of maintainability. So long as you don't shoot yourself in the foot by being "too smart", the less lines of rules, the less chance of hiding some error.

htaccess redirect in joomla WITHOUT landing on index.php

I've added an redirect from an old domain to my new domain in the .htaccess file of my Joomla 3.x site, running on Apache.
This is the code I'm trying to get working;
RewriteCond %{HTTP_HOST} !newdomain\.co\.uk$ [NC]
RewriteRule ^(.*)$ http\:\/\/www\.newdomain\.co\.uk/$1 [R=301,L]
This succeeds in redirecting any incorrect domain to my new domain, but does NOT put me on the corresponding sub-page.
So, for example, I type in the following address ..;
http:\\old.com\calendar
... and I WANT to end up at;
http:\\newdomain.co.uk\calendar
But instead, I get directed to;
http:\\newdomain.co.uk\index.php
Can anyone help me get the redirect working to land me on the corresponding sub-page?
For the record, the Joomla site's SEO settings are as follows (and work as you would expect - site pages do not generally include index.php in the URL and correspond to the menu item alias);
Search Engine Friendly URLs - YES
Use URL rewriting - YES
Adds Suffix to URL - NO
Unicode Aliases - NO
The COMPLETE .htaccess file looks like this - I don't know if Joomla's .htaccess definitions are affecting the redirect that I've put in place;
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule .* index.php [F]
RewriteBase /
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteCond %{REQUEST_URI} /component/|(/[^.]*|\.(php|html?|feed|pdf|vcf|raw))$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
suPHP_ConfigPath /whatever/php.ini
RewriteCond %{HTTP_HOST} !newdomain\.co\.uk$ [NC]
RewriteRule ^(.*)$ http\:\/\/www\.newdomain\.co\.uk/$1 [R=301,L]
Header set X-UA-Compatible "IE=10"
Thanks in advance to anyone who can provide some insight!
You are rewriting a lot of stuff to index.php before already – so when your new Rules you added below that are evaluated, the (internal) request URI most likely is index.php already.
So move those new rules further up.

htaccess RewriteCond to let requests for website.com/m/... stay untouched

From a phone, if the user tries to access website.com, they are redirected to mobile.website.com. However, mobile.website.com makes AJAX requests to website.com, so I make all requests go through website.com/m/.... This isn't working:
# redirect phones/tablets to mobile site
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteCond %{HTTP_HOST} !mobile\.website\.com [NC]
RewriteCond %{REQUEST_URI} !^/m/ [NC]
RewriteRule ^(.*)$ http://www.mobile.website.com/$1 [L,R=302]
Specifically the line:
RewriteCond %{REQUEST_URI} !^/m/ [NC]
It should cancel the rewrite rule if the url matches website.com/m/.... Any ideas?
Thanks!
Change your code with this:
# redirect phones/tablets to mobile site
RewriteCond %{HTTP_USER_AGENT} (android|blackberry|ipad|iphone|ipod|iemobile|opera [NC]mobile|palmos|webos|googlebot-mobile) [NC]
RewriteCond %{HTTP_HOST} !mobile\.website\.com$ [NC]
RewriteRule ^(?!m/).*$ http://www.mobile.website.com%{REQUEST_URI} [L,R,NC]
Also if this still doesn't work then please post matching lines from your Apache's access.log and error.log.