Is it possible to have nested ReWrite Conditions in htaccess? - .htaccess

I have the following situation where I want to have nested ReWrite Conditions, and I have come across a situation where I am not able to see a proper documentation for the same.
RewriteCond %{REQUEST_URI} ^(robots.txt|favicon|ico)$ [NC]
RewriteRule . - [S=3]
# Nested ReWrite Condition
RewriteCond %{HTTP_HOST} ^www
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI_1} [R=301,L]
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI_2} [R=301,L] # and so on
Therefore, the question comes up that whether the number of skip rules will comprise of the nested ReWrite Conditions, that is, in this case, should the number of skipped rewrite rules be 4 or 5(if including the rewrite condition).

RewriteCond %{REQUEST_URI} ^(robots.txt|favicon|ico)$ [NC]
RewriteCond %{HTTP_HOST} !^www
RewriteRule .* - [S=3]
# the following rules are run only if the first 2 conditions don't match
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI_1} [R=301,L]
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI_2} [R=301,L]
notice the ! negation in the 2nd cond
documentation:
This technique is useful because a RewriteCond only applies to the
RewriteRule immediately following it. Thus, if you want to make a
RewriteCond apply to several RewriteRules, one possible technique is
to negate those conditions and add a RewriteRule with a [Skip] flag.

Okay as you only have posted an example, I show you an example how it works. It's with comments, but if you still don't find it speaking enough, there is a lot more explanation available here.
# Does the file exist?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Create an if-then-else construct by skipping 3 lines if we meant to
# go to the "else" stanza.
RewriteRule .? - [S=3]
# IF the file exists, then:
RewriteRule (.*\.gif) images.php?$1
RewriteRule (.*\.html) docs.php?$1
# Skip past the "else" stanza.
RewriteRule .? - [S=1]
# ELSE...
Rewri
This should solve your issue. If not, please update your example in the question so it's clear what you're missing.
And yes, it skips Rules and not Conditions.

Related

.htaccess ModRewrite with 2 parameters

#anubhava provided an excellent answer for my previous question of doing an .htaccess internal rewrite with the below code, which worked for my one search query.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} id=([0-9]+) [NC]
RewriteRule ^file\.php$ /directory/%1? [R=301,L,NC]
RewriteRule ^directory/(\d+)/?$ /directory/file.php?id=$1 [L,QSA,NC]
I wanted to make this a separate question since my next question is slightly different. How could I adapt this to also work with two parameters? For instance, I would also like http://ipaddress/directory/file.php?id=47?name=value1 to redirect to http://ipaddress/directory/47/value1
name= can also be any combination of letters and numbers, like value1050, etc.
Thank you #anubhava for your previous answer above, and maybe there's a way to add on this second parameter as well?
Considering you are segregating your query string values in id=1234&name=value123 style, since passing 2 times query string will not be allowed, then you could try following, fix of your shown attempt.
RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^id=(\d+)&name=(.*)$ [NC]
RewriteRule ^file\.php/?$ /directory/%1/%2? [R=301,L,NC]
RewriteRule ^directory/(\d+)/(.*)/?$ /directory/file.php?id=$1&name=$2 [L,QSA,NC]
2nd solution: Adding 1 more solution here, either use above OR use following one at a time only please.
RewriteEngine on
RewriteCond %{THE_REQUEST} \s/file\.php\?d=(\d+)&name=(\S+)\s [NC]
RewriteRule ^ /directory/%1/%2? [R=301,L]
RewriteRule ^directory/(\d+)/(.*)/?$ /directory/file.php?id=$1&name=$2 [NC,L,QSA]

.htaccess RewriteCond and condition not working as expected

I'm trying to get a series of rewrite conditions working, with the logic being this
if condition1 or
(condition2 and condition3) or
..
This is what I have in the .htaccess:
RewriteCond %{HTTP_USER_AGENT} "iphone" [OR,NC]
RewriteCond %{HTTP_USER_AGENT} "android&mobile" [OR,NC]
RewriteCond %{HTTP_USER_AGENT} "iemobile" [NC]
Unfortunately, it looks like the and operator isn't working as I thought it would.
(as you might guess, the idea is to detect android phones but not tablets)
Is there a way to write that and condition to achieve the results I'm looking for?
Thanks.
Unfortunately, the [OR] flag doesn't work as nice enough for it to be useful, it only works for either all "or"'d or all "and"'d conditions. It's not very predictable. What you may need to do is separate them out to several rules and either use the S flag to skip stuff or the pass-through.
Maybe something along the lines of:
# Prevent rewrite looping
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
# if "iphone" OR
RewriteCond %{HTTP_USER_AGENT} "iphone" [NC]
RewriteRule ^ - [S=3]
# "android" AND "mobile", OR
RewriteCond %{HTTP_USER_AGENT} "android" [NC]
RewriteCond %{HTTP_USER_AGENT} "mobile" [NC]
RewriteRule ^ - [S=2]
# "iemobile"
RewriteCond %{HTTP_USER_AGENT} "iemobile" [NC]
RewriteRule ^ - [S=1]
# skip everything, none of the conditions match
RewriteRule ^ - [L]
# apply the rule
RewriteRule ^ /do-something [L]
Looks like a mess but that's mod_rewrite for you.
The first rule is to prevent any sort of internal rewrite looping. The "# skip everything" rule is the one that gets applied if none of the 3 conditions match, it essentially does nothing excepts stops any rewriting. If you have other rules after all of this stuff that you want to get applied, you can replace the L flag with S=1.
The last rule is the rule that gets applied if any of the 3 conditions matches.

htaccess replacing underscores with hyphens

Is there a more efficient way to doing this?
The last /(.*)$ is an ID that I don't care to use. only whats before it.
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5-$6-$7-$8-$9-$10 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5-$6-$7-$8-$9 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5-$6-$7-$8 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5-$6-$7 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5-$6 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2 [NC]
I found some solutions online but seem to get really confused on using the [N] flag? Not too sure here. Can anyone explain a better more efficient way to do this?
You can just let the rewrite engine loop internally for this:
RewriteRule ^about-us/news-room/(.+)/(.*)$ index.php?go=/news/press-releases/$1 [L,NC]
RewriteCond %{QUERY_STRING} ^go=/news/press-releases/(.*)_(.*)$
RewriteRule ^index\.php$ /index.php?go=/news/press-releases/%1-%2 [L]
The first rule sends the request to index.php, and the second rule removes the underscores and replaces them with dashes. Because the rewrite engine loops, it'll keep applying the rule until either the recursion limit is reached or all the underscores are gone.

mod_reweite htaccess not work with a point in var

I creating a mod_rewrite rule like this
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME}\.php !-f
RewriteRule ^(.*)$ ./page.php?key=$1
it works! But I want to do this:
www.site.com/var1.var2.var3
(variables are separated by point) separated by - or _ no problems, but if I put the point does not work why?
I assume that you are trying a rule like this
RewriteRule ^(.*).(.*).(.*)$ ./page.php?key=$1&key2=$2&key3=$3
but you should remember to escape the dots which you want to interpret as periods. There are many ways to right this but here is a simple way if you are new to .htaccess files:
RewriteEngine On
RewriteBase /
# Skip existing files or directories
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule ^ - [L]
# Add default PHP extension when appropriate
RewriteCond %{SCRIPT_FILENAME}.php -f
RewriteRule ^.* $0.php [L]
# Pick up 1,2 and 3 parameter versions
RewriteRule ^(.*?)\.^(.*?)\.(.*)$ page.php?key=$1&key2=$2&key3=$3 [QSA,L]
RewriteRule ^(.*?)\.(.*?)$ page.php?key=$11&key2=$2 [QSA,L]
RewriteRule ^(.*?)\.$ page.php?key=$1 [QSA,L]
Note:
the first rule uses "^" as a pattern which always matches and the "-" means don't replace it.
the second uses $0 which means the entire match pattern
rule 3-5 match the 3,2,1 parameter options
the [L] (last) flag means skip the rest of the rules
you will need the QSA flag is you use other parameters.
The reason for splitting the existance check in to is that you need to handle files such as CSS and image (PNG/GIF/PNG) files as well as your application syntax.

Help with .htaccess RewriteRule. Need to take user from one URL to other

I want users who type
http://www.example.com/word-of-the-day
to be taken to
http://www.example.com/index.php?page=word-of-the-day
But I want
http://www.example.com/word-of-the-day
to be shown in the URL for the user.
What should I do in my .htaccess? I tried but the regular expression
and the syntax of RewriteRule is way too complicated for me to
figure out how to do it.
Any help will be appreciated.
Edit:
Also, how can I say this in htaccess -
if they type http://www.example.com/word-of-the-day, take them to http://www.example.com/index.php?page=word-of-the-day
or if they type http://www.example.com/something-else, take them to http://www.example.com/index.php?page=something-else
or else, just take them to the URL they typed.
The condition below checks that index.php is not being requested. If not apply the rule. This will work for any of the scenarios you listed above.
RewriteCond %{QUERY_STRING} ^!.*[index\.php].*$ [NC]
RewriteRule ^(.*)$ index.php?page=$1 [L]
In response to your comment about only wanting to do this for a few specific pages, it would look like this(as an alternative to Nils edit):
RewriteCond %{QUERY_STRING} ^!.*[index\.php].*$ [NC]
RewriteCond %{REQUEST_URI} ^word-of-the-day$ [OR]
RewriteCond %{REQUEST_URI} ^something-else$ [OR]
RewriteCond %{REQUEST_URI} ^even-something-else$
RewriteRule ^(.*)$ index.php?page=$1 [L]
Try this
RewriteEngine on
RewriteRule ^word-of-the-day$ index.php?page=word-of-the-day
Or more flexible
RewriteEngine on
RewriteRule ^(.*)$ index.php?page=$1
Not tested, yet it sould work.
To your edit:
Just define those specific URLs manually:
RewriteEngine on
RewriteRule ^word-of-the-day$ index.php?page=word-of-the-day
RewriteRule ^word-some-example$ index.php?page=some-example
RewriteRule ^some-other$ index.php?page=some-other

Resources