A few days ago I blogged about a code review I was doing for another client. Yesterday I found another interesting bug in their code. (It is always easier to find bugs in other people's code.)
The code in question was an API tester for their web site. The page had a nice set of links to let you test all of their XML based responses for their site. I noticed something odd in one test. The first time I ran the test, I got a nicely formatted XML result in the browser. The second time however I got an odd jumble of text.
Viewing the source revealed that the XML was there ok. I took a look at the code and spotted the problem right away. See if you can as well:
<cf_ScopeCache
cachename="foo_#somevar#"
scope="server"
timeout="1800">
<cfset myXML = application.myGateway.getMyXML(args)/>
<CFCONTENT TYPE="text/xml" RESET="Yes">
<CFOUTPUT>#ToString(myXML)#</CFOUTPUT>
</cf_scopecache>
If you don't recognize cf_scopecache, it is just a caching custom tag. It takes the text result of the stuff inside it and stores it.
And that's where our problem is. Our caching tag caches the text. But the CFCONTENT tag is a Request specific tag. By that I mean it changes the current request. The first time the page is hit, it will execute, as will all the code inside the scopeCache custom tag. The second time though only the text is returned. CFCONTENT isn't run. The fix was simple - move the CFCONTENT:
<CFCONTENT TYPE="text/xml" RESET="Yes">
<cf_ScopeCache
cachename="foo_#somevar#"
scope="server"
timeout="1800">
<cfset myXML = application.myGateway.getMyXML(args)/>
<CFOUTPUT>#ToString(myXML)#</CFOUTPUT>
</cf_scopecache>
The same issue would exist if you used CFCACHE on top of the page.
Archived Comments
Might be a good idea if you are doing server side caching to add better support for client side caching of the document also. Then check with CF to see if they already have a valid client side copy and have them use that. Adding a last modified or etag header values to the page. Etags works well if you have the same page serving multiple documents then you know if they already have that specific document. Then if a client sends a valid cache info in the http request you can simply send a 304 response and abort the page. Thus saving the processing and the bandwidth.
Good point there. CFCACHE could be updated for that. ScopeCache probably won't as I didn't intend it really to be used for an _entire_ page - just clumps of text.