Search code examples
regexweb-config

How do I capture and redirect files ending in .cfm in web.config minus index.cfm?


I have a site with a homepage at index.cfm. The page content is included based on a URL parameter, so example.com/about (which is rewritten in the web.config file to index.cfm?p=about) will include about.cfm. I want to keep people from accessing files such as about.cfm directly, ideally permanently redirecting them to /about, but I obviously need to allow access to index.cfm since not excluding it from the rule results in infinite redirects.

The rule I created (which should also theoretically allow access to files in the /ajax/ directory) is:

<rule name="don't allow direct access to .cfm pages" stopProcessing="true">
  <match url="^(.+[^\/ajax\/]\/)?([^\/]+[^index]).cfm$" />
  <action type="Redirect" redirectType="Permanent" url="{R:1}/{R:2}" />
</rule>

According to the tester at regex101.com, this should not select 1, 2, and 4 in the list below (as desired), selects 3 (as desired), but captures the entirety of index.cfm?p=contact in 5, which I suspect is the problem:

  1. http://example.com/contact

  2. http://example.com/index.cfm?p=contact

  3. http://example.com/contact.cfm

  4. http://example.com/ajax/contact-form.cfm

  5. http://example.com/index.cfm?p=contact.cfm

If I visit example.com/contact.cfm it gets redirected to https://example.com/index.cfm?p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=index&p=contact, even if it's the only rule in the file, but following is the code to prettify the URL anyway:

<rule name="Prettify URL" stopProcessing="true">
  <match url="^(.+\/)?([^\/]+)$" />
  <conditions logicalGrouping="MatchAll">
    <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="{R:1}index.cfm?p={R:2}" appendQueryString="false" />
</rule>

Where am I going wrong? Thanks!


Solution

  • Try something like this:

    <rule name="don't allow direct access to .cfm pages" stopProcessing="true">
      <match url="^(?!ajax)(?!index\.cfm)(.*?).cfm.*$" />
      <action type="Redirect" redirectType="Permanent" url="index.cfm?p={R:1}" />
    </rule>
    

    This rule should redirect request to any .cfm page (except index.cfm and those in ajax folder if any) to desired URL.

    Here regex ^(?!ajax)(?!index\.cfm)(.*?).cfm.*$ is used. It uses negative lookaheads to prevent matching anything starting with ajax or index.cfm.

    Demo at regex101.

    Where am I going wrong?

    I'm not sure on correctness of your web.config, but your regex was very wrong. [^index] means non of the letters i, n, d, e, x, for example. I recommend read this answer to grasp some understanding in regexes.