16

I have read the top 30 Google hits for several combinations of IIS rewrite map condition and so on, but I can't find any decent documentation, either on a microsoft.com site or elsewhere.

I have a bunch of rewrite maps in IIS7 that I would like to process irrespective of whether or not they are followed by a trailing slash. So www.foo.com/bar and www.foo.com/bar/ should both match the rule.

<rewrite>
    <rewriteMaps>
        <rewriteMap name="ShortURLs">
            <add key="/terms" value="/en-us/terms-and-conditions/"/>
            <add key="/privacy" value="/en-us/privacy-and-cookies/"/>
            <add key="/buy" value="/en-us/where-to-buy/"/>
        </rewriteMap>
    </rewriteMaps>
    <rules>
        <rule name="Short URL redirects">
            <match url="^/?(.+)/?$" />
            <conditions>
                <add input="{ShortURLs:{REQUEST_URI}}" pattern="(.+)"/>
            </conditions>
            <action type="Redirect" url="{C:1}" appendQueryString="true"/>
        </rule>
    </rules>
</rewrite>

Now this works perfectly well, except that the only way I can find to make /terms/ match the first key in the rewrite map is to duplicate the map, so that it reads:

<rewriteMap name="ShortURLs">
    <add key="/terms" value="/en-us/terms-and-conditions/"/>
    <add key="/privacy" value="/en-us/privacy-and-cookies/"/>
    <add key="/buy" value="/en-us/where-to-buy/"/>

    <add key="/terms/" value="/en-us/terms-and-conditions/"/>
    <add key="/privacy/" value="/en-us/privacy-and-cookies/"/>
    <add key="/buy/" value="/en-us/where-to-buy/"/>
</rewriteMap>

This seems ridiculously inelegant, given that I'm using regular expressions to match them in the first place. Adding /? to the condition input or the condition pattern doesn't seem to work.

I have seen the answer to IIS7 Rewrite Map Regex? that mentions regular expressions cannot be used (quoting from Using Rewrite Maps in URL Rewrite Module) but, as I have commented there, this seems to relate to the specific examples being given before that text, rather than a wholesale "this can never work".

What am I missing? There must be some means of doing this; am I missing something obvious?

Community
  • 1
  • 1
Owen Blacker
  • 4,117
  • 2
  • 33
  • 70

2 Answers2

23

This should do it:

<rewrite>
    <rewriteMaps>
        <rewriteMap name="ShortURLs">
            <add key="terms" value="/en-us/terms-and-conditions/"/>
            <add key="privacy" value="/en-us/privacy-and-cookies/"/>
            <add key="buy" value="/en-us/where-to-buy/"/>
        </rewriteMap>
    </rewriteMaps>
    <rules>
        <rule name="Short URL redirects">
            <match url="^(.+?)/?$" />
            <conditions>
                <add input="{ShortURLs:{R:1}}" pattern="(.+)" />
            </conditions>
            <action type="Redirect" url="{C:1}" appendQueryString="true"/>
        </rule>
    </rules>
</rewrite>

You were quite close; I only needed to make three small changes:

  • removed the leading slashes in the keys in the rewrite map
  • used the non-greedy quantifier +? in the rule's match
  • used a back reference to the match {R:1} in the condition input

I share your experience in having trouble finding decent documentation; I had to experiment my way through, with help from the following articles:

Ruud Helderman
  • 10,563
  • 1
  • 26
  • 45
0

Firstly, don't use dot, it matches everything and is naturally greedy. Use character negation instead: ([^\n]+). Try this, then re-run, and if that doesn't work, try adding /? again on the pattern attribute.

Jamie Howarth
  • 3,273
  • 3
  • 20
  • 26
  • All the examples use dot, fwiw. My question is effectively "what regular expressions can we use at all?" — if I set `pattern` to `([^\n]+/?)` or `([^\n]+/?)` and remove the rewrite map with `key="/buy/"`, then passing in `www.foo.com/buy` works, but `www.foo.com/buy/` still 404s. Sorry, no cigar for Ben :) – Owen Blacker Mar 26 '14 at 13:19