iismod-rewriteurl-rewritingquestion2answer

IIS URL Rewrite equivalent for Question2Answer mod_rewrite


What IIS URL Rewrite rule set in web.config is equivalent to this mod_rewrite rule set provided in Question2Answer's default .htaccess?

DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
#RewriteBase /
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php?qa-rewrite=$0&%{QUERY_STRING} [L]
</IfModule>

The rule differs from a typical WordPress-style rewrite in that nested path elements need to be passed through. Following is an example of a test URL that Question2Answer uses to verify rewriting is working, when Question2Answer is deployed into a qa directory on the server (deployment to the web root fails similarly):

http://localhost:32568/qa/url/test/%24%26-_~%23%25%5C%40%5E%2A%28%29%3D%21%28%29%5D%5B%60%27%3B%3A%7C%22.%7B%7D%2C%3C%3E%3F%23+%CF%80%C2%A7%C2%BD%D0%96%D7%A9?dummy=&param=%24%26-_%7E%23%25%5C%40%5E%2A%28%29%3D%21%28%29%5D%5B%60%27%3B%3A%7C%22.%7B%7D%2C%3C%3E%3F%23+%CF%80%C2%A7%C2%BD%D0%96%D7%A9

This is what IIS Manager's "Import mod_rewrite rules" feature came up with:

<rewrite>
   <rules>
      <rule name="Imported Rule 1" stopProcessing="true">
      <match url="." ignoreCase="false" />
      <conditions>
         <add input="{URL}" pattern="^(.*)//(.*)$" ignoreCase="false" />
      </conditions>
      <action type="Redirect" redirectType="Permanent" url="{C:1}/{C:2}" />
      </rule>
      <rule name="Imported Rule 2" stopProcessing="true">
      <match url="^.*$" ignoreCase="false" />
      <conditions>
         <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
         <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
      </conditions>
      <action type="Redirect" url="index.php?qa-rewrite={R:0}&amp;{QUERY_STRING}" appendQueryString="false" />
      </rule>
   </rules>
</rewrite>

I also added this so that the test URLs would fail in the same way as the actual navigation URLs:

<security>
   <requestFiltering allowDoubleEscaping="true" />
</security>

There is no answer to a question covering this on question2answer QA's site. Hopefully someone experienced in IIS URL Rewrite here will know.


Solution

  • This configuration works:

    <?xml version="1.0"?>
    <configuration>
      <system.webServer>
    
        <rewrite>
          <rules>
            <rule name="DeduplicateSlashes" stopProcessing="true">
              <match url="." ignoreCase="false" />
              <conditions>
                <add input="{URL}" pattern="^(.*)//(.*)$" ignoreCase="false" />
              </conditions>
              <action type="Redirect" redirectType="Permanent" url="{C:1}/{C:2}" />
            </rule>
            <rule name="CleanRouting" stopProcessing="true">
              <match url="^.*$" ignoreCase="false" />
              <conditions>
                <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
              </conditions>
              <action type="Rewrite" url="index.php?qa-rewrite={R:0}&amp;{QUERY_STRING}" appendQueryString="false" />
            </rule>
          </rules>
        </rewrite>
    
        <!-- Double escaping is needed for URLs with '+', e.g. for the account page for a username with a space. -->
        <security>
           <requestFiltering allowDoubleEscaping="true" />
        </security>
    
      </system.webServer>
    </configuration>