Score:0

Applying IIS rewrite rules from multiple web.configs for single request

it flag

I am trying to configure a directory structure in an IIS website with rewrite rules applying at various levels. For example, consider the following structure:

Default Web Site
├─ web.config
└─ v1
   ├─ web.config
   └─ wwwroot
      └─ hello.txt

I want to be able to access hello.txt through http://localhost/hello.txt. I have configured the web.config at the website root level like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Rewrite to v1" stopProcessing="false">
          <match url="^(?!v1).*" />
          <action type="Rewrite" url="v1\{R:0}" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

And I have configured the web.config in the v1 directory like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Rewrite to wwwroot" stopProcessing="false">
          <match url="^(?!wwwroot).*" />
          <action type="Rewrite" url="wwwroot\{R:0}" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

The one-level rewrite works when I access http://localhost/v1/hello.txt, but the two-level rewrite doesn't work for http://localhost/hello.txt. The IIS error page shows that the request is still resolving to the physical path …\v1\hello.txt rather than …\v1\wwwroot\hello.txt; see https://i.stack.imgur.com/KjdH5.png. Note that changing the rewrites to redirects allows the file to be served successfully.

Is there a way of getting this to work, or it is some limitation of the URL Rewrite Module? Microsoft seems to claim that this is supported in the URL Rewrite Module Configuration Reference:

Rules Inheritance

If rules are defined on multiple configuration levels, the URL Rewrite Module evaluates the rules in the following order:

  1. Evaluate all the global rules.
  2. Evaluate a rule set that includes distributed rules from parent configuration levels as well as rules from the current configuration level. The evaluation is performed in a parent-to-child order, which means that parent rules are evaluated first and the rules defined on a last child level are evaluated last.

I'm aware that I can make the web.config at the website root level reference the inner wwwroot directory directly (through url="v1\wwwroot\{R:0}"). However, I don't want to do this. I will eventually be extending the outer web.config to support other versions (v2, v3, …), which may or may not also have a wwwroot subdirectory, so it would be much cleaner to maintain any version-specific rewrites to inner subdirectories in the version-specific web.config.

I've tried using Failed Request Tracing. The outer rule, Rewrite to v1, is logged to run successfully. There is no mention of the inner rule, Rewrite to wwwroot.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.