Help with 2 simple rules and [L]

Oct 31, 2008 at 5:55 PM
Edited Oct 31, 2008 at 6:00 PM

I would like to implement 2 simple rules (Ionic ISAPI Rewriting Filter (IIRF) v1.2.15 final R3):

1) if a url is in the form of   http://domain.com/~username/<path>,  redirect to the relative path under the web site document root "/Personal/username/<path>"
2) Otherwise, if the url is an alias to the site and in the form of    http://VirtualSite.domain.com/<path>,  redirect to the relative path under the web site document root "/VirtualSite/<path>"

Here's what I have so far:


RewriteRule ^/~([^/]+)(.*) /Personal/$1$2 [L]

RewriteCond %{HTTP_HOST} ^([^.]+)\.wlu\.edu$

RewriteRule (.*) /%1$1 [L]


1) If I start with http://home2.wlu.edu, I get "/home2" in the redirect.  This is good.
2) If I start with http://home2.wlu.edu/SubFolder , I get "/home2/SubFolder" (what I want) and then the rewrite engine fires again, turning the url into "/home2/home2/SubFolder"
3) If I start with http://home2.wlu.edu/~jknudson , I get "/Personal/jknudson" (what I want) and then the rewrite engine fires again, turning the url into "/home2/Personal/jknudson/"

Hopefully this is a simple case of me not implementing the Last directive correctly.  Any help is appreciated.   Log level 3 details are below.

Details of 2)
Fri Oct 31 12:43:53 -  1628 - HttpFilterProc: SF_NOTIFY_AUTH_COMPLETE
Fri Oct 31 12:43:53 -  1628 - DoRewrites
Fri Oct 31 12:43:53 -  1628 - DoRewrites: New Url: '/SubFolder'
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: depth=0
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: Rule 1 : -1 (No match)
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: Rule 2 : 2 matches
Fri Oct 31 12:43:53 -  1628 - EvalCondition: ts1 'home2.wlu.edu'
Fri Oct 31 12:43:53 -  1628 - ApplyCaseConversion: after  'home2.wlu.edu'
Fri Oct 31 12:43:53 -  1628 - EvalCondition: checking 'home2.wlu.edu' against pattern '^([^.]+)\.wlu\.edu$'
Fri Oct 31 12:43:53 -  1628 - EvalCondition: match result: 2 (match)
Fri Oct 31 12:43:53 -  1628 - EvalCondition: returning TRUE
Fri Oct 31 12:43:53 -  1628 - EvalConditionList: rule 2, TRUE, Rule will apply
Fri Oct 31 12:43:53 -  1628 - ApplyCaseConversion: after  '/home2/SubFolder'
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: Result (length 16): /home2/SubFolder
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: Last Rule
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: returning 1
Fri Oct 31 12:43:53 -  1628 - DoRewrites: Rewrite Url to: '/home2/SubFolder'
Fri Oct 31 12:43:53 -  1628 - HttpFilterProc: SF_NOTIFY_URL_MAP
Fri Oct 31 12:43:53 -  1628 - HttpFilterProc: SF_NOTIFY_URL_MAP
Fri Oct 31 12:43:53 -  1628 - HttpFilterProc: SF_NOTIFY_AUTH_COMPLETE
Fri Oct 31 12:43:53 -  1628 - DoRewrites
Fri Oct 31 12:43:53 -  1628 - DoRewrites: New Url: '/home2/SubFolder/'
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: depth=0
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: Rule 1 : -1 (No match)
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: Rule 2 : 2 matches
Fri Oct 31 12:43:53 -  1628 - EvalCondition: ts1 'home2.wlu.edu'
Fri Oct 31 12:43:53 -  1628 - ApplyCaseConversion: after  'home2.wlu.edu'
Fri Oct 31 12:43:53 -  1628 - EvalCondition: checking 'home2.wlu.edu' against pattern '^([^.]+)\.wlu\.edu$'
Fri Oct 31 12:43:53 -  1628 - EvalCondition: match result: 2 (match)
Fri Oct 31 12:43:53 -  1628 - EvalCondition: returning TRUE
Fri Oct 31 12:43:53 -  1628 - EvalConditionList: rule 2, TRUE, Rule will apply
Fri Oct 31 12:43:53 -  1628 - ApplyCaseConversion: after  '/home2/home2/SubFolder/'
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: Result (length 23): /home2/home2/SubFolder/
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: Last Rule
Fri Oct 31 12:43:53 -  1628 - EvaluateRules: returning 1
Fri Oct 31 12:43:53 -  1628 - DoRewrites: Rewrite Url to: '/home2/home2/SubFolder/'
Fri Oct 31 12:43:53 -  1628 - HttpFilterProc: SF_NOTIFY_URL_MAP


Details of 3)

Fri Oct 31 12:50:01 -  1628 - HttpFilterProc: SF_NOTIFY_URL_MAP
Fri Oct 31 12:50:01 -  1628 - HttpFilterProc: SF_NOTIFY_AUTH_COMPLETE
Fri Oct 31 12:50:01 -  1628 - DoRewrites
Fri Oct 31 12:50:01 -  1628 - DoRewrites: New Url: '/~jknudson'
Fri Oct 31 12:50:01 -  1628 - EvaluateRules: depth=0
Fri Oct 31 12:50:01 -  1628 - EvaluateRules: Rule 1 : 3 matches
Fri Oct 31 12:50:01 -  1628 - ApplyCaseConversion: after  '/Personal/jknudson'
Fri Oct 31 12:50:01 -  1628 - EvaluateRules: Result (length 18): /Personal/jknudson
Fri Oct 31 12:50:01 -  1628 - EvaluateRules: Last Rule
Fri Oct 31 12:50:01 -  1628 - EvaluateRules: returning 1
Fri Oct 31 12:50:01 -  1628 - DoRewrites: Rewrite Url to: '/Personal/jknudson'
Fri Oct 31 12:50:01 -  1628 - HttpFilterProc: SF_NOTIFY_URL_MAP
Fri Oct 31 12:50:01 -  1628 - HttpFilterProc: SF_NOTIFY_URL_MAP
Fri Oct 31 12:50:01 -  1628 - HttpFilterProc: SF_NOTIFY_AUTH_COMPLETE
Fri Oct 31 12:50:01 -  1628 - DoRewrites
Fri Oct 31 12:50:01 -  1628 - DoRewrites: New Url: '/Personal/jknudson/'
Fri Oct 31 12:50:01 -  1628 - EvaluateRules: depth=0
Fri Oct 31 12:50:01 -  1628 - EvaluateRules: Rule 1 : -1 (No match)
Fri Oct 31 12:50:01 -  1628 - EvaluateRules: Rule 2 : 2 matches
Fri Oct 31 12:50:01 -  1628 - EvalCondition: ts1 'home2.wlu.edu'
Fri Oct 31 12:50:01 -  1628 - ApplyCaseConversion: after  'home2.wlu.edu'
Fri Oct 31 12:50:01 -  1628 - EvalCondition: checking 'home2.wlu.edu' against pattern '^([^.]+)\.wlu\.edu$'
Fri Oct 31 12:50:01 -  1628 - EvalCondition: match result: 2 (match)
Fri Oct 31 12:50:01 -  1628 - EvalCondition: returning TRUE
Fri Oct 31 12:50:01 -  1628 - EvalConditionList: rule 2, TRUE, Rule will apply
Fri Oct 31 12:50:01 -  1628 - ApplyCaseConversion: after  '/home2/Personal/jknudson/'
Fri Oct 31 12:50:01 -  1628 - EvaluateRules: Result (length 25): /home2/Personal/jknudson/
Fri Oct 31 12:50:01 -  1628 - EvaluateRules: Last Rule
Fri Oct 31 12:50:01 -  1628 - EvaluateRules: returning 1
Fri Oct 31 12:50:01 -  1628 - DoRewrites: Rewrite Url to: '/home2/Personal/jknudson/'
Fri Oct 31 12:50:01 -  1628 - HttpFilterProc: SF_NOTIFY_URL_MAP


Coordinator
Oct 31, 2008 at 7:19 PM
Edited Nov 11, 2008 at 4:06 PM
You mentioned a redirect, but I don't see a redirect in your rules.
Are you giving me the whole story? Or maybe you mean "rewrite" instead of "redirect"?
The log file for case #2 shows 2 distinct requests coming through. The [L] flag is properly used; you can see in the log output that it says "Last Rule". The request is rewritten and all is well. Then there is a new Url request that comes through. Where is this 2nd request coming from? This could be the result of some logic in your page, or something in the browser...
What resides at the server address "/Personal/jknudson" ? What will run on the server side if I key in that URL into the browser? What will the browser get back in response? (you can see this with a logger like Fiddler)
I can imagine modifying Rule #2 so that it does not fire if the URL is of the form "vdir.wlu.edu/vdir/..." But based on your rules, I don't see what that would be necessary. There seems to be something else that is causing multiple requests to be sent into the filter. So, putting in a modification in the rule would just mask the problem, if you know what I mean. We're not understanding what's really happening.
One way to track this down is to use a browser-side logger, something like Fiddler2, to examine the http transactions that get sent out from the browser. Fiddler2 works with IE, but there is something similar for FF. With that you should be able to correlate the browser-side log with the IIRF log and see how many requests get sent out, when, why, etc.
For example if the server sent back a response with a meta refresh header, then the browser, by convention, will process this response and send a new request out. This is similar to a 302 redirect, except it is done with an 200 OK document. If I looked at the browser transaction log I would see 2 requests sent out, and 2 responses.
anyway, it bears further investigation.


Nov 3, 2008 at 7:43 PM
You are correct, I mean rewrite (redirect is part of another project and I mixed my terms).

I re-ran the query for http://home.wlu.edu/~jknudson , with a packet trace which showed that an intermediate 301 redirect is being generated by the first rule, which causes the browser to then request the new URL

  • Time Protocol Info
  • 18.524207 TCP 2688 > http [SYN] Seq=0 Len=0 MSS=1460
  • 18.524653 TCP http > 2688 [SYN, ACK] Seq=0 Ack=1 Win=16384 Len=0 MSS=1460
  • 18.524684 TCP 2688 > http [ACK] Seq=1 Ack=1 Win=65535 Len=0
  • 18.524948 HTTP GET /~jknudson HTTP/1.1
  • 18.632903 HTTP HTTP/1.1 301 Moved Permanently (text/html)
  • 18.634141 HTTP GET /Personal/jknudson/ HTTP/1.1
  • 18.636062 TCP [TCP segment of a reassembled PDU]
  • 18.636135 HTTP HTTP/1.1 404 Not Found (text/html)
  • 18.636178 TCP 2688 > http [ACK] Seq=1564 Ack=2176 Win=65535 Len=0

Here are the details from the HTML in the 301 redirect packet:

  • Hypertext Transfer Protocol
  • HTTP/1.1 301 Moved Permanently\r\n
  • Content-Length: 162
  • Content-Type: text/html\r\n
  • Location: http://home2.wlu.edu/Personal/jknudson/\r\n
  • Server: Microsoft-IIS/6.0\r\n
  • X-Powered-By: ASP.NET\r\n
  • Date: Mon, 03 Nov 2008 19:30:53 GMT\r\n
  • \r\n
  • Line-based text data: text/html
  • <head><title>Document Moved</title></head>\n
  • <body><h1>Object Moved</h1>This document may be found <a HREF="http://home2.wlu.edu/Personal/jknudson/">here</a></body>

The details from the rewrite log for this transaction are:

  • Mon Nov 03 14:30:53 -  3120 - Initialize: Ionic ISAPI Rewriting Filter (IIRF) v1.2.15 final R3
  • Mon Nov 03 14:30:53 -  3120 - Initialize: config file 'C:\Inetpub\wwwroot\IsapiRewrite4.ini'
  • Mon Nov 03 14:30:53 -  3120 - Initialize: File watcher thread created.
  • Mon Nov 03 14:30:53 -  3120 - GetFilterVersion
  • Mon Nov 03 14:30:53 -  3120 - HttpFilterProc: SF_NOTIFY_URL_MAP
  • Mon Nov 03 14:30:53 -  3120 - HttpFilterProc: SF_NOTIFY_AUTH_COMPLETE
  • Mon Nov 03 14:30:53 -  3120 - DoRewrites
  • Mon Nov 03 14:30:53 -  3120 - DoRewrites: New Url: '/~jknudson'
  • Mon Nov 03 14:30:53 -  3120 - EvaluateRules: depth=0
  • Mon Nov 03 14:30:53 -  3120 - EvaluateRules: Rule 1 : 3 matches
  • Mon Nov 03 14:30:53 -  3120 - ApplyCaseConversion: after  '/Personal/jknudson'
  • Mon Nov 03 14:30:53 -  3120 - EvaluateRules: Result (length 18): /Personal/jknudson
  • Mon Nov 03 14:30:53 -  3120 - EvaluateRules: Last Rule
  • Mon Nov 03 14:30:53 -  3120 - EvaluateRules: returning 1
  • Mon Nov 03 14:30:53 -  3120 - DoRewrites: Rewrite Url to: '/Personal/jknudson'
  • Mon Nov 03 14:30:53 -  3120 - HttpFilterProc: SF_NOTIFY_URL_MAP
  • Mon Nov 03 14:30:53 -  3120 - HttpFilterProc: SF_NOTIFY_URL_MAP
  • Mon Nov 03 14:30:53 -  3120 - HttpFilterProc: SF_NOTIFY_AUTH_COMPLETE
  • Mon Nov 03 14:30:53 -  3120 - DoRewrites
  • Mon Nov 03 14:30:53 -  3120 - DoRewrites: New Url: '/Personal/jknudson/'
  • Mon Nov 03 14:30:53 -  3120 - EvaluateRules: depth=0
  • Mon Nov 03 14:30:53 -  3120 - EvaluateRules: Rule 1 : -1 (No match)
  • Mon Nov 03 14:30:53 -  3120 - EvaluateRules: Rule 2 : 2 matches
  • Mon Nov 03 14:30:53 -  3120 - EvalCondition: ts1 'home2.wlu.edu'
  • Mon Nov 03 14:30:53 -  3120 - ApplyCaseConversion: after  'home2.wlu.edu'
  • Mon Nov 03 14:30:53 -  3120 - EvalCondition: checking 'home2.wlu.edu' against pattern '^([^.]+)\.wlu\.edu$'
  • Mon Nov 03 14:30:53 -  3120 - EvalCondition: match result: 2 (match)
  • Mon Nov 03 14:30:53 -  3120 - EvalCondition: returning TRUE
  • Mon Nov 03 14:30:53 -  3120 - EvalConditionList: rule 2, TRUE, Rule will apply
  • Mon Nov 03 14:30:53 -  3120 - ApplyCaseConversion: after  '/home2/Personal/jknudson/'
  • Mon Nov 03 14:30:53 -  3120 - EvaluateRules: Result (length 25): /home2/Personal/jknudson/
  • Mon Nov 03 14:30:53 -  3120 - EvaluateRules: Last Rule
  • Mon Nov 03 14:30:53 -  3120 - EvaluateRules: returning 1
  • Mon Nov 03 14:30:53 -  3120 - DoRewrites: Rewrite Url to: '/home2/Personal/jknudson/'
  • Mon Nov 03 14:30:53 -  3120 - HttpFilterProc: SF_NOTIFY_URL_MAP

So it does appear that I'm generating a redirect and not the rewrite to the path "/Personal/jknudson" that I'm trying to achieve.  What is the correct syntax to get a local path rewrite without the redirect?

Thank you.
JK

Coordinator
Nov 4, 2008 at 6:57 PM
Edited Nov 4, 2008 at 7:39 PM
RewriteRule gives you rewrite.
RedirectRule gives you redirect.

IIRF will log something like 
DoRewrites: Rewrite Url to: '/home2/Personal/jknudson/'

...when  it performs a rewrite.  It will log something like: 
DoRewrites: Redirect (code=301) Url to: '/home2/Personal/jknudson/'

... when it performs a redirect.  Your IIRF log file indicates that IIRF is doing only rewrites.   Something else is doing the redirect.  Is it possible you have an ASP.NET module that might be replying with an HTTP 301?


If you look closely at your IIRF log, you will see the 1st request gets rewritten as "/Personal/jknudson" .  The 2nd request comes in as "/Personal/jknudson/" . They are not the same - the 2nd adds a trailing slash.  What is adding the slash?  It does not appear to be IIRF doing that.  Not according to the log file!

My understanding, from your browser transaction log and your IIRF log, is that IIRF is REWRITING the ~jknudson to /Personaljknudson  .  There is a server-side application responding to that request - it is not IIRF that responds.  The response from the unknown server-side app is an HTTP 301, pointing to '/Personal/jknudson/' .  The browser receives the 301 and then makes another request, to '/Personal/jknudson/' , as it should.  IIRF then rewrites that request also, and it rewrites it to a strange place, which gives you a 404.


Soooooo: 2 issues.
- find the unknown app that is responding with HTTP 301
- update the IIRF ini file so that if IIRF gets a request to '/Personal/jknudson/' ,  it just works.  Maybe it doesn't rewrite, maybe it strips the trailing slash, whatever.

I suspect that if you fixed ONLY the 2nd issue, you will have an infinite loop - because, with no Rewrite, the request to '/Personal/jknudson/'  will go to the unknown app, and the unknown app will return HTTP 301, and the browser will request '/Personal/jknudson/' , and so on, and so on. . .
Nov 11, 2008 at 3:09 PM
Any luck fixing the problem? I have a similar one.

GET /forums/topic/1 HTTP/1.1
Accept: */*
Referer: http://87.110.186.15/forums/
Accept-Language: lv
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; InfoPath.2)
Connection: Keep-Alive
Host: 87.110.186.15

Response:
HTTP/1.1 200 OK
Connection: close
Date: Tue, 11 Nov 2008 14:49:49 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Content-Type: text/html; charset=UTF-8
Refresh: 0;url=http://87.110.186.15/forums/topic/1





Nov 11, 2008 at 3:17 PM
No joy.  I rebuilt the virtual Windows test server from scratch to verify that there was no "unknown app" contributing to my problems with the rewrite code.  I re-installed IIS, set up the ISAPI fileter and reproduced the exact problem reported above.  I then shut down IIS, installed Apache 2.2 for Windows, and configured mod_rewrite with the exact same directives listed above.  It works perfectly under Apache / mod_rewrite.  I now just need to decide if I want to support 2 different web servers on the same box, seperated by different secondary IP addresses, of course.  I don't mind Apache on Windows, I've run it for years on RedHat and Windows 2003 server, however, support for Linux is thin here, and my goal was to consolidate my mass virtual hosting onto IIS, where we have plenty of capable administrators.
Nov 11, 2008 at 3:28 PM
My problem looks like a specific bbpress issue - http://bbpress.org/forums/topic/infinite-loops-on-posts-and-profiles
Coordinator
Nov 11, 2008 at 4:02 PM
jknudson - are you able to get a browser-side log of the situation?
a log from Fiddler or some other client-side logger.  FF works with Fiddler, but it also has a different logger, whose name I cannot recall.

Nov 12, 2008 at 2:42 PM
My Nov 3 post above includes a client-side trace using the Wireshark packet sniffer to capture all HTTP traffic between my client and the test server showing that a 301 redirect was generated by the server, causing the re-GET.

I am using IE 7 on Windows XP at the client and IIS6 on Windows 2003 Server R2 32 bit at the server.

I have installed Fiddler and re-set up my test server with the following .ini file:

  • RewriteLog C:\MVH\rewrite.log
  • RewriteLogLevel 5
  • RewriteRule ^/~([^/]+)(.*) /Personal/$1$2 [L]

The document root of this site contains a top level folder named "Personal" with a sub folder "jknudson" which contains an index.htm file.
The Fiddler trace below is of me entering the URL http://mapdev.ad.wlu.edu/~jknudson to the IsapiRewrite4 enabled IIS site.
If I do this in Apache/mod_rewrite, the browser URL remains as /~jknudson and I am presented with the index page.  If I run this rule through the IsapiRewrite4 enabled IIS site, I get a 301 redirect to the URL /Personal/jknudson which then expectedly redirects to /Personal/jknudson/index.htm .  The URL in the browser has now been changed to /Personal/jknudson/ which is not what I was looking for.


 

 

 

 

 

GET /~jknudson HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, */*
Accept-Language: en-us
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)
Host: mapdev.ad.wlu.edu
Connection: Keep-Alive
Cookie: __utma=44263906.3580457862115054000.1214244461.1225899167.1225903377.80; __utmz=44263906.1225903377.80.18.utmcsr=managementtools.wlu.edu|utmccn=(referral)|utmcmd=referral|utmcct=/template/
X-NovINet: v1.2

HTTP/1.1 301 Moved Permanently
Content-Length: 166
Content-Type: text/html
Location: http://mapdev.ad.wlu.edu/Personal/jknudson/
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Wed, 12 Nov 2008 14:24:47 GMT

 


 

 

 

GET /Personal/jknudson/ HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, */*
Accept-Language: en-us
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)
Host: mapdev.ad.wlu.edu
Connection: Keep-Alive
X-NovINet: v1.2
Cookie: __utma=44263906.3580457862115054000.1214244461.1225899167.1225903377.80; __utmz=44263906.1225903377.80.18.utmcsr=managementtools.wlu.edu|utmccn=(referral)|utmcmd=referral|utmcct=/template/

HTTP/1.1 200 OK
Content-Length: 8
Content-Type: text/html
Content-Location: http://mapdev.ad.wlu.edu/Personal/jknudson/index.htm
Last-Modified: Mon, 10 Nov 2008 18:16:35 GMT
Accept-Ranges: bytes
ETag: "3c285776043c91:3f1"
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Wed, 12 Nov 2008 14:24:47 GMT

The rewrite.log for this transaction is as follows:

  • Wed Nov 12 09:24:47 -  3376 - HttpFilterProc: SF_NOTIFY_URL_MAP
    Wed Nov 12 09:24:47 -  3376 - OnUrlMap: storing physical path (\\mess1\wwwtest\~jknudson), in ptr (0x000c1760)
    Wed Nov 12 09:24:47 -  3376 - HttpFilterProc: SF_NOTIFY_AUTH_COMPLETE
    Wed Nov 12 09:24:47 -  3376 - DoRewrites
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: getting 'url'
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree - no joy (GetLastError()=1413)
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: 128 bytes
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: result ''
    Wed Nov 12 09:24:47 -  3376 - GetHeader_AutoFree: getting 'url'
    Wed Nov 12 09:24:47 -  3376 - GetHeader_AutoFree: 11 bytes, result '/~jknudson'
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: getting 'QUERY_STRING'
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: 1 bytes
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: result ''
    Wed Nov 12 09:24:47 -  3376 - GetHeader_AutoFree: getting 'method'
    Wed Nov 12 09:24:47 -  3376 - GetHeader_AutoFree: 4 bytes, result 'GET'
    Wed Nov 12 09:24:47 -  3376 - DoRewrites: New Url: '/~jknudson'
    Wed Nov 12 09:24:47 -  3376 - EvaluateRules: depth=0
    Wed Nov 12 09:24:47 -  3376 - EvaluateRules: Rule 1 : 3 matches
    Wed Nov 12 09:24:47 -  3376 - ReplaceServerVariables: InputString='/Personal/$1$2' out='/Personal/$1$2'
    Wed Nov 12 09:24:47 -  3376 - GenerateReplacementString: src='/~jknudson','(null)' ReplacePattern='/Personal/$1$2' vec=[[  [  0, 10, 2, 10, 10, 10] [] ] counts=3,0
    Wed Nov 12 09:24:47 -  3376 - GenerateReplacementString: replacing ($1) with 'jknudson'
    Wed Nov 12 09:24:47 -  3376 - GenerateReplacementString: replacing ($2) with ''
    Wed Nov 12 09:24:47 -  3376 - ApplyCaseConversion: before '/Personal/jknudson'
    Wed Nov 12 09:24:47 -  3376 - ApplyCaseConversion: after  '/Personal/jknudson'
    Wed Nov 12 09:24:47 -  3376 - GenerateReplacementString: result '/Personal/jknudson'
    Wed Nov 12 09:24:47 -  3376 - EvaluateRules: Result (length 18): /Personal/jknudson
    Wed Nov 12 09:24:47 -  3376 - EvaluateRules: Last Rule
    Wed Nov 12 09:24:47 -  3376 - EvaluateRules: returning 1
    Wed Nov 12 09:24:47 -  3376 - DoRewrites: Rewrite Url to: '/Personal/jknudson'
    Wed Nov 12 09:24:47 -  3376 - HttpFilterProc: SF_NOTIFY_URL_MAP
    Wed Nov 12 09:24:47 -  3376 - OnUrlMap: storing physical path (\\mess1\wwwtest\Personal\jknudson), in ptr (0x000c1788)
    Wed Nov 12 09:24:47 -  3376 - HttpFilterProc: SF_NOTIFY_URL_MAP
    Wed Nov 12 09:24:47 -  3376 - OnUrlMap: storing physical path (\\mess1\wwwtest\Personal\jknudson\), in ptr (0x000c7720)
    Wed Nov 12 09:24:47 -  3376 - HttpFilterProc: SF_NOTIFY_AUTH_COMPLETE
    Wed Nov 12 09:24:47 -  3376 - DoRewrites
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: getting 'url'
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree - no joy (GetLastError()=1413)
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: 128 bytes
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: result ''
    Wed Nov 12 09:24:47 -  3376 - GetHeader_AutoFree: getting 'url'
    Wed Nov 12 09:24:47 -  3376 - GetHeader_AutoFree: 20 bytes, result '/Personal/jknudson/'
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: getting 'QUERY_STRING'
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: 1 bytes
    Wed Nov 12 09:24:47 -  3376 - GetServerVariable_AutoFree: result ''
    Wed Nov 12 09:24:47 -  3376 - GetHeader_AutoFree: getting 'method'
    Wed Nov 12 09:24:47 -  3376 - GetHeader_AutoFree: 4 bytes, result 'GET'
    Wed Nov 12 09:24:47 -  3376 - DoRewrites: New Url: '/Personal/jknudson/'
    Wed Nov 12 09:24:47 -  3376 - EvaluateRules: depth=0
    Wed Nov 12 09:24:47 -  3376 - EvaluateRules: Rule 1 : -1 (No match)
    Wed Nov 12 09:24:47 -  3376 - EvaluateRules: returning 0
    Wed Nov 12 09:24:47 -  3376 - DoRewrites: No Rewrite
    Wed Nov 12 09:24:47 -  3376 - HttpFilterProc: SF_NOTIFY_URL_MAP
    Wed Nov 12 09:24:47 -  3376 - OnUrlMap: storing physical path (\\mess1\wwwtest\Personal\jknudson\index.htm), in ptr (0x000b38b8)


Nov 19, 2008 at 3:43 AM
Is there anything else I can provide to solve this issue or should I wait for version 2 to come out and re-test then to see if it behaves more like mod_rewrite?
Thanks.
JK
Coordinator
Dec 1, 2008 at 2:32 AM
Sorry about the delay. This is sort of a labor of love for me, I do it in my spare time and had some things come up where spare time became much more rare.
It's not a version 1.2.x versus version 2.x thing.  The filter will use the same pattern matching logic, by and large, the same model for hooking into the IIS server.
It looks like an issue with request processing.  Let me have a look at it.
again.

Coordinator
Dec 1, 2008 at 3:07 AM
Edited Dec 1, 2008 at 3:35 AM
Ok, this is weird.  The good news is that I reproduced the situation here -
With your simple ini file (one single rule) I am seeing the 301 response code, too.

An update - I just removed all IIRF from the IIS configuration, and I still see the 301 response code.
If I send a request as http://myserver/Personal/jknudson , it gets a response code of 301 with the new location set to http://myserver/Personal/jknudson/  .   

This is not IIRF doing the 301; it appears to be IIS.  Just WHY IIS would send a 301 is not clear to me.

It makes sense, I guess, when you are browsing a directory, that IIS might want to append a trailing slash.  I mean, it's kind of sneaky, that IIS is doing this without telling us.  (Maybe it is in the doc but I haven't seen it?)  But it's not entirely surprising. 

So that part of the mystery is cleared up.  It is not clear whether the IIS behavior can be tweaked or disabled.

Re-enabling the IIRF and using a rule to REWRITE a request like ~jknudson to /Personal/jknudson/index.htm, causes the expected behavior:  There is no 301 generated, and I get the contents of the index.htm file from the mapped directory.  The address in the browser bar remains at http://myserver/~jknudson  .

I will look into why IIS is sending back the 301 for directory browsing., and if it is possible to disable.   Maybe you can look, too.


Coordinator
Dec 1, 2008 at 3:46 AM
Edited Dec 1, 2008 at 4:17 AM

I learned something today.
It is IIS generating the 301 response. 
See this article for more info: 
http://support.microsoft.com/kb/298408

So far I have not learned if it is possible to disable it.

You can avoid the IIS 301 "courtesy redirect" if you modify your rewrite rule slightly, to be like so:

 RewriteLog  c:\temp\iirf-v1.2.15.log
RewriteLogLevel 5
RewriteRule ^/~([^/]+)(.*) /Personal/$1$2/ [L]

Note the trailing slash on the replacement string. You would probably want to tighten that up a bit to take care of the case where there is already a trailing slash.

Dec 1, 2008 at 4:43 PM
Thank you very much for looking into this.

I did some testing of the trailing slash concept, and it works for directories and full paths to files.  I would have to test the URL to see if it was a directory, instead of a path to a file, and then test for the trailing slash and append one if needed.  Does that sound about right?

While testing this idea I did run into one more oddity.  If you configure IIS to allow directory browsing, browse to a folder with no index file such as http://home2.wlu.edu/~jknudson/ (including trailing slash), then you are presented with a list of files in the folder, as expected, but the title of the directory index is "home2.wlu.edu - /Personal/jknudson/", the expanded path that we want hidden.  However, in this case, clicking on the file xyz.htm results in the URL http://home2.wlu.edu/Personal/jknudson/xyz.htm instead of http://home2.wlu.edu/~jknudson/xyz.htm .  A mouse-over confirms that this is the URL being presented and that this is not a case of another redirect by IIS.  The link works, it's just not the URL I want to advertise.
Coordinator
Dec 1, 2008 at 5:07 PM
Right, well...

I think the way it works is that when "directory browsing" is enabled, IIS itself generates the file list and sends it to the browser.  The file list is not contained in a static file (index.htm) nor is there some sort of dynamic page (index.aspx) that is doing it for you.   It is built into IIS6. 

You have some options.
  1. write your own directory browsing logic, called "default.asp" or something, that presents the file list without exposing the true directory name. This works on any version of IIS. http://support.microsoft.com/kb/224364  But it requires the ASP file (or aspx or php or whatever) to be present in each directory, and it requires the directory be a vdir.  see also http://blog.crowe.co.nz/archive/2006/03/18/603.aspx
  2. on IIS7, use the admin UI for IIS to configure it: http://technet.microsoft.com/en-us/library/cc732762.aspx or for IIS7, there is a directory browse module, an ASPX file you can set yourself. 
  3. Build a separate piece of server-side logic that does this once.   Rewrite incoming URLs of rht form ~jknudson to the script (eg, DirBrowse.aspx?user=jknudson) which produces the directory listing you like. 
Dec 1, 2008 at 5:32 PM
I totally agree that IIS is doing the page generation, just as Apache does it when it is running.  I was just pointing out a difference in the way the directory browsing URL is handled with IIS verses Apache.  If I turn off IIS and turn on Apache2.2 using the exact same rules and paths on the same server, the directory browsed page is titled "Index of ~jknudson" and selecting the xyz.htm link results in the URL http://home2.wlu.edu/~jknudson/xyz.htm .  So Apache/mod_rewrite is preserving the pre-rewrite version of the URLs when the browsing page is generated while IIS is using the post-rewrite URLs.  This just sounds like it's a difference between Apache and IIS and whether the directory page is generated using the origional or re-written URLs.

I don't think many people use browsing, I have it off by default now, but overridable in an access control file on a per-directory basis (in Apache).  I'll scan for access control files that enable this and if the number of sites that use it are small, then I like your option 1 above for generating a directory listing without using the built in IIS logic by just distributing an asp or aspx file to those directories needing it.