Question

I am running CF10 on IIS 7.5 with URL Rewrite module installed. All the rewrite rules work perfectly and ColdFusion is returning the correct pages. In order to get the page displayed in the browser I have to manually set the 'content-length' value in Application.cfc like this:

<cfcomponent>

  <cffunction name="onRequestEnd">

  <cfheader name="Content-Length" value="#getPageContext().getCFOutput().getBuffer().size()#" />

  </cffunction>

</cfcomponent>

Without this code the browser does not display the page. However, even though it is now displaying the page, it is not doing it correctly. The page never finishes loading fully and not all of the HTML content seems to be on the page.

I have tried to add a <cfflush /> tag after setting the 'content-length' but it makes no difference. I don't understand why this is happening but I know that it has happened to someone else who was using htaccess:http://forums.devshed.com/coldfusion-development-84/page-not-finishing -loading-coldfusion-and-htaccess-bug-575906.html

EDIT: Example Outbound/Inbound Rule Definition:

<!--- Outbound rule --->
<rule name="Rewrite Info Page" preCondition="IsHTML" enabled="false" stopProcessing="false">
<match filterByTags="A" pattern="^(.*)/info\.cfm\?subjectid=([^=&amp;]+)&amp;(?:amp;)?nameid=([^=&amp;]+)$" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
</conditions>
<action type="Rewrite" value="{R:1}/info/{R:2}/{R:3}" />
</rule>

<preConditions>
<preCondition name="IsHTML">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>


<!--- Inbound rule --->
<rule name="Rewrite Info Page" enabled="true" stopProcessing="false">
<match url="^(.*)/info/([^/]+)/([^/]+)/?$" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="{R:1}/info.cfm?subjectid={R:2}&amp;nameid={R:3}" appendQueryString="true" />
</rule>

The Outbound rule is looking at a URL link within an <a> tag that looks like http://mysite.com/info.cfm?subjectid=1&nameid=1 and then rewriting it to appear on my page as http://mysite.com/info/1/1.

The Inbound is looking for a link that looks like http://mysite/info/1/1 and resolving/rewriting it to the real URL which is http://mysite.com/info.cfm?subjectid=1&nameid=1

Was it helpful?

Solution

Since IIS URL Rewrite's outbound rules are giving you so much trouble, here is another option. Use ColdFusion to rewrite the links in onRequestEnd. This will allow you to use physical paths in your IDE, use default documents, and still get the outbound URLs sent to the browser in the desired format. I've updated my Gist with the details.

Here is a very basic approach. Turn off the outbound rewrite rule in web.config and add something like this to your onRequestEnd function in Application.cfc. (My regex is horrible, so this reReplace() pattern only partially works the way your IIS pattern did.

<cfcomponent>

    <cffunction name="onRequestEnd">
        <!--- Get the generated output --->
        <cfset var output = getPageContext().getCFOutput().getBuffer().toString()>      

        <!--- Apply outbound link rules --->
        <cfset output = reReplace(output, '/info\.cfm\?subjectid=([^=&amp;]+)', '/info/\1', 'all')>

        <!--- Clear the previous output and send the rewritten output in its place --->
        <cfcontent reset="true">
        <cfoutput>#output#</cfoutput>

    </cffunction>

</cfcomponent>

This won't perform as well as the URL Rewrite module in IIS, but it will give you everything else you are trying to achieve (once you get your regex tuned up).

OTHER TIPS

I was able to get your outbound rules to work pretty much as is on my local dev environment (although running CF9). The only trouble was getting the outbound rules wrapped in the correct XML elements.

After that, IIS told me outbound rules could not be applied to gzipped content, so I had to add <urlCompression doStaticCompression="true" doDynamicCompression="false"/> to the configuration.

With that in place, the outbound rewrite worked perfectly. I even ran it against a page that had over 20,000 links, and it handled it fine.

Here is my <rewrite> section for web.config along with the <urlCompression> bit:

    <rewrite>
        <rules>
            <rule name="Rewrite Info" enabled="true" stopProcessing="false">
                <match url="^(.*)/info/([^/]+)/([^/]+)/?$" />
                <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                </conditions>
                <action type="Rewrite" url="{R:1}/info.cfm?subjectid={R:2}&amp;nameid={R:3}" appendQueryString="true" />
            </rule>
        </rules>
        <outboundRules>
            <rule name="Rewrite Info Page" preCondition="IsHTML" enabled="true" stopProcessing="false">
                <match filterByTags="A" pattern="^(.*)/info\.cfm\?subjectid=([^=&amp;]+)&amp;(?:amp;)?nameid=([^=&amp;]+)$" />
                <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                </conditions>
                <action type="Rewrite" value="{R:1}/info/{R:2}/{R:3}" />
            </rule>
            <preConditions>
                <preCondition name="IsHTML">
                    <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                </preCondition>
            </preConditions>
        </outboundRules>
    </rewrite>
    <urlCompression doStaticCompression="true" doDynamicCompression="false"/>

I found no difference in the result when including <cfheader name="Content-Length" value="#getPageContext().getCFOutput().getBuffer().size()#" /> in onRequestEnd.

However, since you are getting the spinner and the page never seems to fully load, you might try explicitly flushing and closing the response in onRequestEnd to ensure the handoff back to IIS is complete:

<cfscript>
    var response = getPageContext().getResponse().getResponse();
    var out = response.getOutputStream();
    out.flush();
    out.close();
</cfscript>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top