Getting x number of variables in mod_rewrite from "directories" - .htaccess

This rewrite rule works fine for domain.com/news but I would like be able to parse multiple levels into variables like domain.com/news/2012/party/zeke etc
I tried experimenting with the regex but failed badly.
RewriteEngine on
RewriteBase /
RewriteRule ^([^/\.]+)/?$ page.php?page=$1 [L]
Also tried solutions here:
mod_rewrite with multiple variables
using mod_rewrite to simulate multiple sub-directories
// EDIT: It seems I can just add one rule per level BUT is it possibel to have one rule that does all levels?
RewriteRule ^([^/\.]+)/?$ /page.php?page=$1 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ /page.php?page=$1&sub=$2 [L]

You can have recursive rules however all of the parts of your rewrite are data. So how can it be converted to a query string as it does not know how to name the variables.
If you had /section/news/year/2012/user/zeke/ then you could use (NOT TESTED):-
RewriteRule ^section/\w+/([^/]+)/([^/]+)/(.*)$ news/$3?$1=$2 [NC,N,QSA]
RewriteRule ^section/(\w+)/?$ page.php?page=$1 [NC,QSA,L]
This should end up rewriting to `page.php?page=news&year=2012&user=zeke
With what you are trying to do you are going to have to change your requirements and use a version of the above or pass them all down to a page in PHP and do the work in PHP.

Related

Two rules at the same time and their order

I have aim to use two domains (old and new). So when I go to address:
http://old.cz/whatever/whatever
I would like to get to:
http://new.cz/whatever/whatever
Perfectly works for me this thing:
RewriteRule ^(.*)$ http://www.new.cz/$1 [R=301]
But! At the same time I want following. When I go to address:
http://old.cz/
I want to get to:
http://new.cz/specific-page/specific-page
For that works this code:
Redirect 301 / http://new.cz/specific-page/specific-page
My issue is that in case I use both rules at the same time the first one is always prioritize and the second one suppressed. It means that when I go to http://old.cz/ I always get on only to http://new.cz/
Help me please.
Redirect and RewriteRule are directives of two different apache modules mod-alias and mod-rewrite . You can not combine these two directive for url redirection because of their different runtime behaviour. Use RewriteRule instead of Redirect.
RewriteEngine on
RewriteRule ^/?$ http://new.cz/specific-page/specific-page [L,R]
RewriteRule ^(.*)$ http://www.new.cz/$1 [R=301]

Apply htaccess rules for all cases except a few

I want every access to:
www.example.com/demo/action.html
to redirect to
www.example.com/demo/?section=action
Being action the variable that changes.
But, I do not want to apply that rule in a couple of cases, lets say:
www.example.com/demo/mypage1.html
www.example.com/demo/mypage2.html
For those cases I want them to load the real html pages mypage1.html and mypage2.html.
At the moment I have like 20 rules for all possible action variables. But as it doesn't seem to be ideal in terms of performance, I would rather have just the 2 special cases and a single rule for all the other cases.
This is what I have at the moment:
RewriteRule ^demo/removeUser.html$ demo/?section=removeUser [QSA]
RewriteRule ^demo/addUser.html$ demo/?section=addUser[QSA]
RewriteRule ^demo/addUser.html$ demo/?section=editUser[QSA]
RewriteRule ^demo/addUser.html$ demo/?section=comment[QSA]
... etc
You can keep exception at the top and then a generic rewrite rule:
RewriteEngine On
RewriteRule ^demo/(?:mypage1|mypage2)\.html$ - [L,NC]
RewriteRule ^demo/([\w-]+)\.html$ demo/?section=$1 [QSA,L,NC]
This assumes that demo/ directory has no .htaccess inside.
However if you are just looking at excluding all existing files from this rewrite then you just a single rule like this:
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^demo/([\w-]+)\.html$ demo/?section=$1 [QSA,L,NC]

Rewrite basic $_GET variable to friendly URL using mod_rewrite

I know questions similar to this are common. I just don't even know where to begin with rewrite rules with the /'s and .'s I don't know how to retrofit other peoples solutions to mine. Onto my situation:
I am using a basic get on the index.php file that looks like
http://www.example.com/index.php?page=about
I want to rewrite that to
http://www.example.com/about
I know this is fairly simple rewrite wise, but its just a totally different language which I have tried and failed to comprehend. Thanks
Try this:
RewriteEngine on
RewriteRule ^([^/\.]+)/?$ /index.php?page=$1 [L]
Or even:
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(?!index.php\b).* index.php?page=$0 [L,QSA]
Note:
You should always set the RewriteBase in an .htaccess file.
I've generalised this so that index.php picks up any string which isn't mapping to a real file
The (?!index.php\b) is a regexp which says "but don't match to index.php"
You will need the [QSA] flag if your requests can contain request parameters. This merges them.

mod_rewrite doesn't actually... re-write the URL

Basically, I've been trying to make some friendly URL's via .htaccess using mod_rewrite - and I've managed to get it to work... but only with basic stuff like:
RewriteEngine On
RewriteBase /
RewriteRule ^profile.php http://www.google.co.uk [L]
So mod_rewrite works, and I can re-direct to other sites, other files/directories in my server, etc. - but it seems to not work when I use this:
RewriteEngine On
RewriteBase /
RewriteRule ^profile.php?user=$1 ^profile/user/([^/]*)/$ [L]
Any help on this would be great, as I pretty much suck at mod_rewrite, but it's something I need to learn.
Cheers!
Change your [L] to [R,L] to force an actual HTTP redirect. Otherwise it just does the rewriting internally (when possible), which only affects the mapping from the URI to the filesystem. (See the description of the [R] flag at http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriteflags.)
Wrong.
## rewriting from to
RewriteRule ^profile.php?user=$1 ^profile/user/([^/]*)/$ [L]
Should be
## rewriting from to
RewriteRule ^profile/user/([^/]+)$ profile.php?user=$1 [L]
Your configuration currently is this:
RewriteEngine On
RewriteBase /
RewriteRule ^profile.php?user=$1 ^profile/user/([^/]*)/$ [L]
In the RewriteRule you swapped the from and to parameters.
Assuming that on your server there is a directory structure like this:
/var/www/htdocs/profile/user/albert
/var/www/htdocs/profile/user/bob
Then you can use the following rule:
RewriteCond ${QUERY_STRING} ^user=(\w+)$
RewriteRule ^profile\.php$ profile/user/%1 [L]
There are some points that you got wrong here:
The request to "/profile.php?user=bob" first gets split into the Request URI and the Query String. Only the Request URI will be used by mod_rewrite. Therefore you have to handle the query string separately.
I restricted the user name to only [A-Za-z0-9_]. If I had allowed all characters, an attacker could easily call /profile.php?user=../../config.php, which would be rewritten to profile/user/../../config.php, and you probably don't want to share that file with the world.
The arguments to the RewriteRule directive are completely different regarding their syntax.
The first argument (the from part) is a regular expression, which usually starts with a caret ^ and ends with a dollar $.
The second argument (the to part) is the replacement, which is almost only a simple string, with only some special features. This string usually doesn't start with a caret, but looks rather like a pathname.

htaccess - Rewrite rule and/or condition to fix totally different discontinued or incorrect incoming link

Well, I am stuck again. Two days of reading and again, found some close solutions but, nothing fits and all my experiments failed.
This is a continuation of my question:
here at stackoverflow
The 4 rules below take my incoming links:
http://somedomain.com/getme.pl?dothis=display&partnum=1234567
and beatifies it.
Also allows users to use the beatified version right in address bar:
http://somedomain.com/1234567
Here are my working rules:
RewriteRule ^([\s]*)$ /getme.pl [L] ## in case there is a space or nothing.
RewriteRule ^([0-9]*)$ /getme.pl?dothis=display&partnum=$1&rewrite [L]
RewriteCond %{QUERY_STRING} partnum=([0-9]*)$
RewriteRule (.*) /%1? [L,R=301]
Works great but, I discovered there are some old links to the site out there:
http://somedomain.com/oldversion.php?id=123456789
And
http://somedomain.com/oldversion.php?r=86this&id=123456789
I would like to just grab the id=[0-9] and integrate it with my working rules.
I suppose, the rule would be inserted between the second and third rules above.
I tried various attempts (about 100!) like:
RewriteRule ^(oldversion\.php)?([a-z]{1})=([a-z0-9]*)&([a-z]{2})=([0-9]*)$ /$4? [L]
RewriteRule ^(oldversion\.php)?([a-z]{2})=([0-9]*)$ /$3? [L]
As you see, two days of reading and nothing is sinking in for me.
I tried several variations of the working rules I already have as well, to no avail.
Can't I just get the 123456789 off of the outdated .php urls somehow and stick it in my existing rules?
Thanks for your help and explaining down to my level co, I just might be able to understand...
Put this at the end of your .htaccess file:
RewriteCond %{QUERY_STRING} id=([^&]+)(&|$) [NC]
RewriteRule ^oldversion\.php$ /%1? [L,R=301,NC,NE]
For a URI of /oldversion.php?r=86this&id=123456789 it will internally redirect to /123456789
Remember RewriteRule just matches your URI and it cannot match your QUERY_STRING.

Resources