Linux-Apache-ModRewrite
From DevRandom
Notes
- REQUEST_URI is URL minus http:// & anything after the ?
- ? makes single character match optional and importantly makes the match non-greedy.
Consider the string "indian" and the need to match any character followed by n
(.*?)n will stop at the first n
(.*)n will parse through the whole string
with (.*)n $1 = "india"
with (.*?)n $1 = "i"
To further demonstrate with perl
# echo "indian" | perl -pe 's|(.*)n|R|' R # echo "indian" | perl -pe 's|(.*?)n|R|' Rdian
- RewriteCond is tried only if RewriteRule is matched. So in the order of execution, RewriteRule comes first.
If the rule matches, then the condition is checked and if the condition is satisfied the rule is executed.
- Rewrite Rules run before the authentication phase.
- Entries in RewriteMap are case sensitive and this cannot be overridden.
- RewriteMap & RewriteLog are not allowed in htaccess
- RewriteCond rules are additive by default
- Cookies can be used for one time redirection
- Besides rewriting URLs, mod_rewrite can be used for proxying, access control & virtual hosting. In almost all cases, it better to use a module
like mod_proxy, mod_access, mod_vhost or mod_vhost_alias. They do a better job and provide better performance.
Examples
Redirect all requests to www.example.com
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.example.com
RewriteRule ^.*?$ http://www.example.com/
Redirect all to a sub folder /example to /example/newsite
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/example/newsite/.*$
RewriteRule ^(.*)$ public/$1 [NC]
Provide www.username.example.com for the homepage of username via just DNS A records to the same machine and without any virtualhosts on this machine
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.[^.]+\.example\.com$
RewriteRule ^(.+) %{HTTP_HOST}$1 [C]
RewriteRule ^www\.([^.]+)\.example\.com(.*) /home/$1$2
Search pages in more than one directory
RewriteEngine on
# first try to find it in custom/...
RewriteCond /docroot/dir1/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /docroot/dir1/$1 [L]
# second try to find it in pub/...
RewriteCond /docroot/dir2/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /docroot/dir2/$1 [L]
Time based rewriting
RewriteEngine on
RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule ^foo\.html$ foo.day.html
RewriteRule ^foo\.html$ foo.night.html
Content based on username Redirect to the users folder based on the user named provided in the authentication scheme
http://example.com/protected/<username> is rewritten to http://example.com/protected/<{REMOTE USERNAME}>
Note: This needs to be tied with authentication directives and directory /var/www/sriramrajan.com/protected must be protected by it.
RewriteEngine On
RewriteCond %{LA-U:remote_user} !^$
RewriteRule ^/protected(.*) /var/www/example.com/protected/%{LA-U:remote_user}/$1
Randomized content
Load a random image from a rewrite map
RewriteMap loadrandom rnd:/etc/httpd/conf/randompic.rnd
RewriteRule ^/nicepic.jpg /randompic/${loadrandom:nicepic}.jpg
RewriteRule ^/garbage.jpg /randompic/${loadrandom:garbage}.jpg
The rnd file contains he following
nicepic photo1|photo2|photo3 garbage photo7|photo6|photo5
Or a poor mans load balancer. Note there are better ways to load balance in Apache also. This is just a demonstration of how mod_rewrite can be used to do that.
RewriteEngine On
RewriteMap loadradom rnd:/etc/httpd/conf/imageservers.rnd
RewriteRule ^/(.*\.png|jpg)) http://${loadrandom:images}/$1 [NC,P,L]
imageservers.rnd contains the followng
images servera|serverb
Clean URLS
Map the URLS to a query argument.
http://example.com/search http://example.com/search/country/US http://example.com/search/country/UK/London http://example.com/search/country/UK/London/Essex to http://example.com/search.php http://example.com/search.php?country=US http://example.com/search.php?country=UK&city=London http://example.com/search.php?country=UK&city=London&county=Essex
The rule looks like this
RewriteWEngine On RewriteRule ^/search/?([^/]*)/?([^/]*)/?([^/]*)/? http://example.com/search.php?country=$1&city=$2&county=$3 [PT]
Redirecting based on User Agents
Note, HTTP_USER_AGENT is reasonably easy to fake. So don't rely on this for any security specific feature.
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} MSIE [NC]
RewriteRule /index.php /index-IE.php? [L,R]
One time redirect
Redirect once per session using cookies. This will break user bookmarks.
RewriteEngine On
RewriteCond %{HTTP_COOKIE} !alreadyhere=1
RewriteRule .* /index.php [R,L]
RewriteRule /index.php - [CO=alreadyhere:1:.example.com]
Rewrite www.subdomain.domain.com to subdomain.domain.com
Credit: Shawn Warren
RewriteCond %{HTTP_HOST} !^subdomain.example.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www.)?([a-z0-9-]+).example.com [NC]
RewriteRule (.*) http://%2.example.com [NC,L]
The first line states, match if the HTTP_HOST is not subdomain.example.com.
The second line states, if the HTTP_HOST begins with 'www' followed by any combination of letters and numbers to form the subdomain name; then match. The first set of '()' form the first back-trace of this rewrite rule, represented by a %1. I have included two back-traces in this rewrite rule but we only reference the second back-trace, %2.
The third and final line is the actual rewrite rule that will take the second back-trace, %2, and rewrite that in place of the subdomain name.
Resources
http://www.addedbytes.com/cheat-sheets/mod_rewrite-cheat-sheet/






