If you're stuck with a situation that requires running Drupal on Windows/IIS/MySQL/PHP (WIMP - an appropriate acronym, huh?), these tips might help.

We had already purchased a product that provides mod_rewrite like functionality for using clean urls on IIS for our main site. Here is the config that we're using to enable it. I also had to go directly into the database to change to clean_url value to s:1:"1"; as I couldn't change it in the default admin section (and didn't take time to investigate what the code was doing), but it seems to work pretty well. If you get a chance, please let me know if there are any gaps and/or the potential for unintended consequences.

[ISAPI_Rewrite]
# http://www.isapirewrite.com/

RepeatLimit 32

# Block external access to the httpd.ini and httpd.parse.errors files
RewriteRule /httpd(?:\.ini|\.parse\.errors).* / [F,I,O]

# Block external access to the Helper ISAPI Extension
RewriteRule .*\.isrwhlp / [F,I,O]

# Rewrite protolive to fully qualified url
RewriteCond Host: connect
RewriteRule (.*) http\://connect.educause.edu$1 [I,R] 


# Accept a url with a period and pass it through unchanged.
#RewriteRule (.*\..*) $1 [I,L]

# Accept a url with .css and pass it through unchanged.
RewriteRule (.*.css) $1 [I,L]

# Accept a url with .js and pass it through unchanged.
RewriteRule (.*.js) $1 [I,L]

RewriteRule /index.php.* $0  [I,L]
	
RewriteRule /(.*)\?(.*) /index.php\?q=$1&$2 [I,L]

RewriteRule /(.*) /index.php\?q=$1 [I,L]

Here is some preliminary code that I'm using to execute the cron script. I just sheduled it to run on a periodic basis. As with the info above, please let me know if there are key gaps that my catch me.


dim ret_value

ret_value = checkpage("http://connect.educause.edu/cron.php")


Dim objFSO
Dim objStream 

Set objFSO = createobject("scripting.filesystemobject")
Set objStream = objFSO.CreateTextFile("c:\inetpub\wwwroot\custom\hit_cron.log", True)

objStream.Writeline ret_value


set objFSO = nothing
set objStream = nothing

Wscript.Quit 


function checkPage(url)

	Dim xmlhttp

	Set xmlhttp = CreateObject("Msxml2.SERVERXMLHTTP")

	xmlhttp.Open "GET", url, false
	xmlhttp.setRequestHeader "Pragma", "no-cache"
	xmlhttp.setRequestHeader "Cache-Control", "no-cache"
	
	on error resume next
	
	xmlhttp.Send

	'Wait for up to 30 seconds if we've not gotten the data yet
	If xmlhttp.readyState <> 4 then
		xmlhttp.waitForResponse 30
	End If
	
	on error resume next
	
	If (xmlhttp.readyState <> 4) Then
		xmlhttp.Abort
		checkPage = "TIMEOUT"
	else
		checkPage = xmlhttp.status
	end if
	
	checkPage = checkPage & " - " & xmlhttp.statusText & " - " & now()

	set xmlhttp = Nothing

End Function

Thanks!

Matt

Comments

sepeck’s picture

You don't need fancy stuff for cron. Just create a user account and run a 'Scheduled Task' to run iexplore "http://sitename.com/cron.php"

-sp
---------
Test sites and good habits: Drupal Best Practices Guide.
Misc Black Mountain

-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide

dan123-1’s picture

Do u put it in the drupal folder. Can u be specfic as to where to make the changes ? Thankx

arcf21’s picture

I installed ISAPI_Rewrite Lite freeware and it worked ok.
But I also had to modify a little the httpd.ini example and set clean urls manually in the database because the settings options didn´t work.

SELECT * FROM variable v WHERE v.name = 'clean_url';

UPDATE variable SET value = 's:1:"1";' WHERE name = 'clean_url';

LIFTHERE’s picture

Images in the default themes where not coming through, so I added:

# Accept a url with .jpg and pass it through unchanged.
RewriteRule (.*.jpg) $1 [I,L]
# Accept a url with .gif and pass it through unchanged.
RewriteRule (.*.gif) $1 [I,L]

# Accept a url with .png and pass it through unchanged.
RewriteRule (.*.png) $1 [I,L]
# Accept a url with .ico and pass it through unchanged.
RewriteRule (.*.ico) $1 [I,L]

You might have to create even more pass throughs to get things to work. Not sure what other solution or maybe more elegant way of writing the above.

One problem, is that I tried the schedule task option to run cron.php which seems to work when clean urls are not on, but with clean urls and the isapi_rewrite I get a 404.

I created another rewrite rule as follows:

# Accept a url with /cron.php and pass it through unchanged.
RewriteRule (/cron.php) $0 [I,L]

So my final ISAPI_rewrite httpd.ini file is:

[ISAPI_Rewrite]
# http://www.isapirewrite.com/
RepeatLimit 32
# Block external access to the httpd.ini and httpd.parse.errors files
RewriteRule /httpd(?:\.ini|\.parse\.errors).* / [F,I,O]
# Block external access to the Helper ISAPI Extension
RewriteRule .*\.isrwhlp / [F,I,O]
# Rewrite protolive to fully qualified url
RewriteCond Host: www
RewriteRule (.*) http\://www.designmiami.us$1 [I,R] 
# Accept a url with a period and pass it through unchanged.
#RewriteRule (.*\..*) $1 [I,L]
# Accept a url with .jpg and pass it through unchanged.
RewriteRule (.*.jpg) $1 [I,L]
# Accept a url with .gif and pass it through unchanged.
RewriteRule (.*.gif) $1 [I,L]
# Accept a url with .png and pass it through unchanged.
RewriteRule (.*.png) $1 [I,L]
# Accept a url with .ico and pass it through unchanged.
RewriteRule (.*.ico) $1 [I,L]
# Accept a url with .css and pass it through unchanged.
RewriteRule (.*.css) $1 [I,L]
# Accept a url with .js and pass it through unchanged.
RewriteRule (.*.js) $1 [I,L]
# Accept a url with /cron.php and pass it through unchanged.
RewriteRule (/cron.php) $0 [I,L]
RewriteRule /index.php.* $0 [I,L]
RewriteRule /(.*)\?(.*) /index.php\?q=$1&$2 [I,L]
RewriteRule /(.*) /index.php\?q=$1 [I,L]

Better solution for running cron on IIS... use the poormancron module http://drupal.org/project/poormanscron

I will revise this comment if i find any bugs and/or fixes.

mlsamuelson@drupal.org’s picture

I'm running Drupal on a server with another non-Drupal site. In order to not have URL rewriting cause conflicts on the non-Drupal site, I used the following in my httpd.ini, before any of my Drupal RewriteRules:

RewriteCond Host: www\.example\.com
RewriteRule (.*) $1 [I,L] 

Essentially, if any www.example.com URLs are requested, we pass everything through and process no further rules. The L flag means, if we match, stop processing rules. Of course we'll match with (.*).

I've copied all of my code below, so you can see it in context. Also, note the simplified RewriteRule syntax for passing extensions through. The | (pipe) is an 'or' operator.

[ISAPI_Rewrite]
# http://www.isapirewrite.com/

# Defend your computer from some worm attacks
RewriteRule .*(?:global.asa|default\.ida|root\.exe|\.\.).* . [F,I,O]

RepeatLimit 32
# Block external access to the httpd.ini and httpd.parse.errors files
RewriteRule /httpd(?:\.ini|\.parse\.errors).* / [F,I,O]
# Block external access to the Helper ISAPI Extension
RewriteRule .*\.isrwhlp / [F,I,O]

# Rewrite www.example.com pages verbatim (since they're not using Drupal)
# the RewriteRule [L] directive means if this rule matches, stop here
RewriteCond Host: www\.example\.com
RewriteRule (.*) $1 [I,L] 

# Accept a url with the following extensions and pass them through unchanged.
RewriteRule (.*.gif|.*.png|.*.jpg|.*.pdf|.*.js|.*.css) $1 [I,L]

# Make URLs sane
RewriteRule /index.php.* $0 [I,L]
RewriteRule /(.*)\?(.*) /index.php\?q=$1&$2 [I,L]
RewriteRule /(.*) /index.php\?q=$1 [I,L]

Hope it's helpful to someone.

And thanks, Matt, for the original post!

Michael

mlsamuelson’s picture

I just discovered one more addition needed so your favicon.ico file can be found.

Alter the rule that lets the special file extensions through so it looks like the following:

# Accept a url with the following extensions and pass them through unchanged.
RewriteRule (.*.gif|.*.png|.*.jpg|.*.pdf|.*.js|.*.css|.*.ico) $1 [I,L]

Michael
mlsamuelson

mlsamuelson

brashquido’s picture

There is a problem with the above rules if you have your download method set to private. Images just don't show up. Am working on a solution now....

www.it-hq.org

brashquido’s picture

The rules shown are this thread are pretty good, but are not complete and should NOT be put blindly into a production site. This of course totally depends on what modules you are using. Isapi_Rewrite does not support file/folder existance checking, and therefore the rules used in .htaccess can not be transferred easily to Isapi_Rewrite, and a rule must be written for each folder/file that needs to be access directly.

I have just found another couple of issue where graphs are not rendered if you are using the GraphStats module, and also any submitted data to the profile module is not saved. I am still working on a solution, and think I'm almost there. Even then it will not be complete, and each new module will need to be tested.

www.it-hq.org

matt_paz’s picture

Does anyone have any ideas about how to configure clean urls in 4.7? Also, my cache settings in 4.7 on WIMP don't seem to be working (settings are being kept).

Thanks!
Matt

brashquido’s picture

I'm still using my 4.6 rules with 4.7 ok, you just have to use a bit of trickery to force Drupal into clean URL mode. See this issue. Haven't noticed any caching issues, but then again I haven't looked (I will now though).

----------------
Dominic Ryan
www.it-hq.org

matt_paz’s picture

I had set
$conf['clean_url'] = 0;
in settings.php while upgrading ... sorry about that.
Same with caching, but I am having an issue there.
I'll start a seperate thread if I can't track it down.

Thanks!
Matt

webavant’s picture

The line: RewriteRule (.*\..*) $1 [I,L] assumes that there will never be a period in the path or query string. Am I missing something? I see that you have the line commented. I am not sure where I originally got the idea to insert this same line in my httpd.ini, but I think it was this post. In mine, there was an additional line to handle several periods in a row also RewriteRule (.*\.*\..*) $1 [I,L] (seems sort of redundant). Anyone know where I copied this from and if I'm going to have problems if I delete it? A google of "Accept a url with a period and pass it through unchanged" only returns this post, so this must be the source. I deleted the rule from my httpd.ini because it was causing problems with IMCE.module using periods in the query string.