Rewrite maps in IIS7 — how to make the match optio

2019-04-20 15:44发布

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?

2条回答
Rolldiameter
2楼-- · 2019-04-20 16:25

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:

查看更多
等我变得足够好
3楼-- · 2019-04-20 16:34

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.

查看更多
登录 后发表回答