Clean urls with isapi rewrite on iis

By Yuka Poppe (Yuka)
Forced to deal with a windows based server, without apache and effectively also mod_rewrite? But, after much complaining and begging your sysadmin has been kind enough to install isapi_rewrite on that (already bloated) iis box... then this is for you!
This article (can this be called an article) is about clean and pretty uri's for cakephp, or anything else with an url dispatcher thingy.

Why, because im not a iis guru (I usually stay as much away from iis as humanly possible), and because of this I had some trouble giving my cake based webapps a nice and elegant url scheme. Allthough there where some skinny isapi_rewrite examples floating around here somewhere, they provided inadequate and not very friendly. The most usefull snippet i found, was directing any requests with a trailing slash to the index.php in the webroot, and the rest was treated as a normal ugly url to make sure your css, img and js dirs where still possible to get to.

So i figured, i do know mod_rewrite pretty ok, and because regexp can get a bit intimidating i decided to publish what i think is a nice way to do things, so here is the httpd.ini / htaccess.ini rewrite rules i've been using for a while now:
Download code
[ISAPI_Rewrite]

RewriteCond URL (?!/js/|/img/|/files/|/css/).*
RewriteRule (.*?\.php)(\?[^/]*)?/([^/]*)/(.*) $1(?2$2&:\?url=/$3/$4)
RewriteCond URL (?!/js/|/img/|/files/|/css/).*
RewriteRule ^/(.*) /index.php?url=/$1 [L]
RewriteCond URL (?!/js/|/img/|/files/|/css/).*
RewriteRule /(.*) /$1


Ofcourse, all files in the webroot are on the same level as the webservers document root. The actual libs and code are outside of the servers docroot, as it should be.

 

Comments 213

CakePHP Team Comments Author Comments
 

Question

1 which file gets replaced

which .htaccess file did you replace?
A standard Cake install has:
/httpdocs/.htaccess
/httpdocs/app/.htaccess
/httpdocs/app/webroot/.htaccess

which file(s) does this httpd.ini replace for?
Posted Aug 15, 2007 by Rob Coenen
 

Comment

2 for v3

# Helicon ISAPI_Rewrite configuration file
# Version 3.0.0.28


RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [L,QSA]
Posted Nov 1, 2007 by tadwook fdfghd
 

Comment

3 slight problem with 3rd rule

If I had a query string already in my url, then the output using rule 3 would cause two '?' in the url.

Test url:
/controller/function/?key1=val1&key2=val2

Original 3rd rule:
RewriteRule ^/(.*) /index.php?url=/$1 [L]

Original Result:
/index.php?url=/controller/function/?key1=val1&key2=val2

The Fix...

New 3rd Rule:
RewriteRule ^/(.*)(\?.*) /index.php$2&url=/$1 [L]

New output:
/index.php?key1=val1&key2=val2&url=/controller/function/

P.S. I am no regular expression expert, so I sure there could be a better solution, and I have not catered for a clean url if url being tested was /controller/function/?, not that this should be problem though. Also, at the moment, the eventual rules would be:

RewriteCond URL (?!/assets/|/js/|/img/|/files/|/css/).*
RewriteRule (.*?\.php)(\?[^/]*)?/([^/]*)/(.*) $1(?2$2&:\?url=/$3/$4)
RewriteCond URL (?!/assets/|/js/|/img/|/files/|/css/).*
RewriteRule ^/(.*)(\?.*) /index.php$2&url=/$1 [L]
RewriteCond URL (?!/assets/|/js/|/img/|/files/|/css/).*
RewriteRule ^/(.*) /index.php?url=/$1 [L]
RewriteCond URL (?!/assets/|/js/|/img/|/files/|/css/).*
RewriteRule /(.*) /$1

I've kept the original 3rd rule, as we need to cater for both plain urls and those with querystrings already in them.
Posted Nov 8, 2007 by Greg Gunner