I have just finished writing a new site. It is a simple blog. The only advice I have received from my readers is that I should consider changing the www.example.com/?page=3 to something like www.example.com/1.
How should I go about writing this rewrite rule?
If your URLs have a common pattern and parts of the externally used URL can directly be mapped onto the internally used URL while retaining a uniquely identifiable URL (like your URL probably does), you can do something like this with mod_rewrite:
RewriteEngine on
RewriteRule ^[0-9]+$ /?page=$1 [L,QSA]
This will rewrite a request of /12345 internally to /?page=12345.
Otherwise, if there isn’t a pattern or the mapping is not trivial, you will probably need to specify each case like:
RewriteEngin on
RewriteRule ^foo$ /?page=1 [L,QSA]
RewriteRule ^bar$ /?page=2 [L,QSA]
RewriteRule ^baz$ /?page=3 [L,QSA]
You could also just pass the request to your PHP file and do the mapping in there.
Related
I've taken my site down for some prolonged maintenance and am using mod_rewrite to send all requests to a single page: www.mysite.com/temp/503.php
This is my .htaccess file which works fine.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/temp/503.php [NC]
RewriteRule .* /temp/503.php [R,L]
However, what I'd also like to be able to do is to hide /temp/503.php in the resulting URL from the visitor.
I know this is perhaps trivial and I'm sure fairly simple to achieve, but with my limited mod_rewrite skills I can't seem to get it to work.
Any help would be much appreciated.
Thanks.
Just get rid of the R flag in the rewrite rule, which tells the rule to redirect the request, thus changing the URL in the browser's location bar. So the rule would look like:
RewriteRule .* /temp/503.php [L]
which internally rewrites the requested URI instead of externally telling the browser that it's been moved to a new URL.
I'm working on clean Url's for my website and I noticed that what you find on the internet is pretty much about rewriting your clean urls to the url that your server can work with. So something like this:
www.domain.com/profile/username --> www.domain.com/profile.php?u=username
RewriteEngine On
RewriteRule ^profile/(.*)$ /profile.php?u=$1 [L]
So now with this I should link within my website to the cleanurl's. But intuitively it feels more solid/better to link to the 'dirty' url. So in that case you should use rewriterules for the above AND a redirect rule to rederict the 'dirty url' to the clean url, so the user only sees the clean url in the browser at all time.
www.domain.com/profile.php?u=username --> www.domain.com/profile/username
Is this something that is a good thing to do. Is it done by websites? What are arguments against/ in favour of it?
And how do you do you do a redirect like this. Something like the following doesn't seem to work:
RewriteRule ^profile\.php?u=(.*)$ /profile/$1 [R=301, L]
I'm fairly new to .htaccess so I might ask for something that's obvious...
RewriteRule ^profile\.php?u=(.*)$ /profile/$1 [R=301, L]
Isn't going to work because you can't match against the query string from a RewriteRule (you also have a stray space in your flags). You also want to be matching against the actual request and not the URI because you'd just cause a redirect loop from your other rule.
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /profile\.php\?u=([^&\ ]+)
RewriteRule ^/?profile\.php$ /profile/%1 [R=301,L]
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.
I'm trying to write a URL like below, but when I try to call the seo queryparam, it always returns index.php. Any idea why it isn't returning the correct value for 'seo'?
RewriteRule ^([^/]*)$ index.php?c=home&m=details&seo=$1 [L]
The URL it should forward from would be something like this: http://domain.com/The-Name-of-the-Product. That URL should be rewritten to http://domain.com/index.php?c=home&m=details&seo=The-Name-of-the-Product, but instead it ends up as http://domain.com/index.php?c=home&m=details&seo=index.php
Various events cause a URL to go back through the rewrite process. You can use RewriteCond to prevent this:
RewriteCond $1 !^index.php$
RewriteRule ^/?([^/]+)$ index.php?c=home&m=details&seo=$1 [L,NS]
From the mod_rewrite technical details:
When you manipulate a URL/filename in per-directory context mod_rewrite first rewrites the filename back to its corresponding URL (which is usually impossible, but see the RewriteBase directive below for the trick to achieve this) and then initiates a new internal sub-request with the new URL. This restarts processing of the API phases.
This catches people all the time.
I have a few messy old URLs like...
http://www.example.com/bunch.of/unneeded/crap?opendocument&part=1
http://www.example.com/bunch.of/unneeded/crap?opendocument&part=2
...that I want to redirect to the newer, cleaner form...
http://www.example.com/page.php/welcome
http://www.example.com/page.php/prices
I understand I can redirect one page to another with a simple redirect i.e.
Redirect 301 /bunch.of/unneeded/crap http://www.example.com/page.php
But the source page doesn't change, only it's GET vars. I can't figure out how to base the redirect on the value of these GET variables. Can anybody help pls!? I'm fairly handy with the old regexes so I can have a pop at using mod-rewrite if I have to but I'm not clear on the syntax for rewriting GET vars and I'd prefer to avoid the performance hit and use the cleaner Redirect directive. Is there a way? and if not can anyone clue me in as to the right mod-rewrite syntax pls?
Cheers,
Roger.
As the parameters in the URL query may have an arbitrary order, you need to use a either one RewriteCond directive for every parameter to check or for every possible permutiation.
Here’s an example with a RewriteCond directive for each parameter:
RewriteCond %{QUERY_STRING} ^([^&]&)*opendocument(&|$)
RewriteCond %{QUERY_STRING} ^([^&]&)*part=1(&|$)
RewriteRule ^bunch\.of/unneeded/crap$ /page.php/welcome? [L,R=301]
RewriteCond %{QUERY_STRING} ^([^&]&)*opendocument(&|$)
RewriteCond %{QUERY_STRING} ^([^&]&)*part=2(&|$)
RewriteRule ^bunch\.of/unneeded/crap$ /page.php/prices? [L,R=301]
But as you can see, this may get a mess.
So a better approach might be to use a RewriteMap. The easiest would be a plain text file with key and value pairs:
1 welcome
2 prices
To define your map, write the following directive in your server or virual host configuration (this directive is not allowed in per-directory context):
RewriteMap examplemap txt:/path/to/file/map.txt
Then you would just need one rule:
RewriteCond %{QUERY_STRING} ^([^&]&)*opendocument(&|$)
RewriteCond %{QUERY_STRING} ^([^&]&)*part=([0-9]+)(&|$)
RewriteRule ^bunch\.of/unneeded/crap$ /page.php/%{examplemap:%2}? [L,R=301]
RewriteCond %{QUERY_STRING} option=com_content&task=view&id=70&Itemid=82
RewriteRule ^index.php http://www.example.com/business/banks/? [R=301,L]
The ? will prevent the url the user is sent to from having the same query string as the origin page.
In summary, you could use RedirectMatch with a regex that will match the full URL, including query string. That will let you rearrange parts of the URL, but if you have to do conversions like "opendocument&part=1" to "welcome" (where the new URL is completely different from the original one), you might need a RewriteMap - or perhaps better, just send all URLs to page.php and parse the query string in PHP.
EDIT: If it's just a few URLs you want to redirect, you could probably write out individual rules like
RedirectPermanent http://www.example.com/bunch.of/unneeded/crap?opendocument&part=1 http://www.example.com/page.php/welcome
RedirectPermanent http://www.example.com/bunch.of/unneeded/crap?opendocument&part=2 http://www.example.com/page.php/prices