Contents Magic

Getting mod_rewrite rewriting

May 19th, 2007 ·

If you're new here, you may want to subscribe to my RSS feed. Thanks for visiting!

A few weeks back I was trying to get the following working, spent several hours and I was about to pull off my hairs.

I need to have a simple url rewriting that translates the following

http://www.tanamtechnologies.com/Web/Computers/Internet

to

http://www.tanamtechnologies.com/database.aspx?c=Category&s=SubCategory

also equally important to me was that I didn’t want any Redirections to happen. This was because I wanted the original URL to remain visible in the address bar and the user should never see that something is being pulled from database dynamically.

Also because I just learned that redirection mod_rewrite is doing will require the browser to make two connections, and that will further create two entries in my log file. I want to avoid these two side effects as well but first one is of prime importance.

At that time I was using win xp as my server. with apache 2.0.55, though I needed to change the OS later on , I stilll run Apache. One great ‘favour’ of Windows was that it did not allow me to rename a file to .htaccess files complaining that I must have a name not just the extension in a filename, I resorted to httpd.conf file. Also Changing the AccessFileName .htaccess to something like AccessFileName htacc.ess did not worked either, but that is probably not hugely important.

So I created a folder named “SecureDirectory” in my docroot and placed a test.aspx there. and placed the following directives in httpd.conf


RewriteEngine on
Options +FollowSymlinks
RewriteRule ^/try\.html$ SecureDirectory/test.aspx [R]

This works in a way that accessing http://www.tanamtechnologies.com/try.html is redirected http://www.tanamtechnologies.com/SecureDirectory/test.aspx but the browser windows shows new url.

when I change the last line to

RewriteRule ^/try\.html$ SecureDirectory/test.aspx

removing the redirection flag, I get a 400 bad request error.

and when I change the last line to it to

RewriteRule ^/try\.html$ http://www.tanamtechnologies.com/SecureDirectory/test.aspx

I do get externally redirected again , with the side effects I mentioned. At this point some one revealed me what I was missing. My understanding was that such redirections are only done by using mod_rewrite in apache, while this is true that mod_rewrite does re-writes the URL, it is only for that purpose. iot will not pull the newly formed URL and supply that to the browser. This is the job of a proxy or in Apache lingo it is done by mod_proxy.

So I went back to my editor and changed the config to have the mod_proxy enabled. Once I figure out the proxy based redirection is working, it was time to get my attention to the real stuff.

So I create the file database.aspx in a folder called “SecureDirectory” with only printing the arguments id , sub, and page back to the browser and see how it works .. but before that we must add the real rule we want to test.

RewriteRule ^/Web/(.*)/(.*)$ SecureDirectory/database.aspx?id=$1&sub=$2 [P]

it works perfectly for the url I had in mind .. so

http://www.tanamtechnologies.com/Web/Computers/Internet

gets perfectly translated to

http://www.tanamtechnologies.com/SecureDirectory/database.aspx?id=Computers&sub=Internet

now we want to have at some pagination on our pages so we would like to have page number variables to re written as well. The following rule is added to httpd.cong

RewriteRule ^/Web/(.*)/(.*)/(.*)$ SecureDirectory/database.aspx?id=$1&sub=$2&page=$3 [P]

and try the url

http://www.tanamtechnologies.com/Web/Computers/Internet/1

what we inted here is that the third (.*) will pick up the page number and the pseudo var $3 will pass that on our file database.aspx. Unfortunatey here is what actually happend. Instead page parameter receives nothing while sub parameter recieves ‘Internet/1′. Two things are happening here. Since we have added the page rule after the first rule, and becasue its kind of a subset its precende is lower and apache is still able to match the requested URI with first rule it encounters.

Secondly, it does encode the ‘/’ before passing the URI to proxy. as a result database.aspx does not receives a value for page .Obviously the solution is to reverse the order so :

RewriteRule ^/Web/(.*)/(.*)/(.*)$ SecureDirectory/database.aspx?id=$1&sub=$2&page=$3 [P]
RewriteRule ^/Web/(.*)/(.*)$ SecureDirectory/database.aspx?id=$1&sub=$2 [P]

works for the url http://www.tanamtechnologies.com/dir/Computers/Internet/1 passing on 1 as the page and Internet as the subcategory . Now the bad news is that it is still not perfect. As the third parameter is the page number and a user may pass http://www.tanamtechnologies.com/dir/Computers/Internet/TCPIP

The first rule can be modified to accept only digits for the third parameter

RewriteRule ^/dir/(.*)/(.*)/(\d*)$ SecureDirectory/database.aspx?id=$1&sub=$2&page=$3 [P]

This ensures that only numbers are passed for the page parameter. However it still does not prevent the above link substituting TCPIP for sub parameter while id gets Computers/Internet. The solution could be using a RewriteCond, but I went the easier way. I put three rules in the order

RewriteRule ^/dir/(.*)/(.*)/(\d*)$ SecureDirectory/database.aspx?id=$1&sub=$2&page=$3 [P]
RewriteRule ^/dir/(.*)/(.*)/(.*)$ SecureDirectory/database.aspx?id=$1&sub=$2&page=0 [P]
RewriteRule ^/dir/(.*)/(.*)$ SecureDirectory/database.aspx?id=$1&sub=$2 [P]

Note the rule in the middle ignores the third parameter and passes 0 for page.Now what is accomplished here will enable us to get the urls translated properly . There are however some security considerations which should also be placed in the server. I will write on those at a later time.

Happy rewriting.
John Doe.

Browse more posts marked in:

;

3 responses so far ↓ I do follow BTW

Leave a Comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>