URL Rewriting And ColdFusion's WriteToBrowser Image Functionality (CFFileServlet)

Posted March 5, 2010 at 9:38 AM

Tags: ColdFusion

Yesterday, as I was experimenting with drawing on an HTML canvas element with jQuery, I was using ColdFusion to render temporary images to the browser. Specifically, I was using the CFImage tag's "WriteToBrowser" action to create a temporary PNG file to be served up by ColdFusion's CFFileServlet. This action creates a image file with the given type of location:

/CFFileServlet/_cf_image/_cfimg-1234567890.PNG

When I first used this approach, none of the temporary ColdFusion images were loading; they were all coming up as 404 file-not-found errors. After a few minutes of confusion, I finally figure out what was going on - my URL rewriting was blocking these temporary image requests:

  • RewriteCond %{REQUEST_FILENAME} !-f
  • RewriteCond %{REQUEST_FILENAME} !-d
  • RewriteRule ^(.+)$ index.cfm/$1 [NC,L,QSA]

As you can see, this rewrite rule gets applied if the requested file is neither a valid file nor a valid directory. Since the ColdFusion CFFileServlet directory doesn't exist in a physical way, my URL rewriting was redirecting the request over to my front-controller (which was then trying to evaluate it as an action).

To get around this, I had to add a rewrite condition to my IIS MOD-Rewrite access file to ignore the rewrite if the requested file was in the CFFileServlet directory:

  • RewriteCond %{REQUEST_FILENAME} !-f
  • RewriteCond %{REQUEST_FILENAME} !-d
  •  
  • # Allow CFFileServlet requests through since they are Voodoo!
  • RewriteCond %{REQUEST_URI} !(?i)^[\\/]CFFileServlet
  •  
  • RewriteRule ^(.+)$ index.cfm/$1 [NC,L,QSA]

With this IIS-MOD Rewrite condition in place, the ColdFusion temporary images started showing up quite nicely. Notice that the rewrite condition checks the REQUEST_URI variable, not the REQUEST_FILENAME. This is because the REQUEST_FILENAME give us the full file path on the server; we can't use this because we only want to allow URLs with the root directory, "CFFileServlet". As such, we need to check the REQUEST_URI, which gives us the script name off of the server.




Reader Comments

Mar 5, 2010 at 9:58 AM // reply »
3 Comments

I found the exact same issue with using <CFCHART> and the CFIDE directory. CFCHART doesn't actually need access to CFIDE, the servletfilter just needs to work.


Mar 5, 2010 at 10:01 AM // reply »
8,836 Comments

@Shannon,

Ah, good call. I have not done too much with charting. I assume it's using the same temporary image servlet then?


Mar 5, 2010 at 10:11 AM // reply »
3 Comments

the charts end up using a URL like this:

/CFIDE/GraphData.cfm?graphCache=someval&graphID=Images/abiglongnumber.SWF

I solved the problem by creating an empty "CFIDE" directory in the root of my site.


Mar 5, 2010 at 10:31 AM // reply »
3 Comments

For multihomed web servers it's useful to create an alias to avoid resolving the same issue over and over.
Apache rule is
Alias /CFFileServlet {ColdFusion dir}/tmpCache/CFFileServlet"

For IIS there should be something under admin for creating virtual directories...


Mar 5, 2010 at 6:22 PM // reply »
5 Comments

This is also true for the CF Administrator, RDS (and Remoting, I think). All of these are disconnected from the need to have actual physical files on the filesystem. RDS and perhaps Remoting will break if you enable a "verify if file exists" option using either a rewrite rule or the IIS configuration option.


Mar 6, 2010 at 9:14 AM // reply »
8,836 Comments

@Shannon, @Jura, @Dave,

I gotcha - so just having the directory there gives the pipeline something to hook into (even if it's not using any of the local files). Makes sense.


Mar 9, 2010 at 1:29 PM // reply »
11 Comments

Our application framework uses 404 handling to create web friendly URLs and serve all sorts of mime types. It's nice to have all the logic for serving pages inside the framework itself (rather than Apache/IIS), but causes issues in getting/parsing post data.

Anyways, we run into similar issues and I try at all costs to avoid using the default ColdFusion file servlets. When possible, I end up making my own handlers by handling the bytearrays myself.

One of my bigger grips with ColdFusion is that it wants to "simplify" too much sometimes without giving options for handling it yourself if you wish to do so (i.e. no CF I don't want you to create the bytearray AND serve it/write it to disk, give it back to me and I will handle it). Most of the newer tags support bytearrays for input but some still want to handle serving the file or writing to the file system... Ugh.


Mar 10, 2010 at 10:05 PM // reply »
8,836 Comments

@Rocky,

Yeah, I know what you mean re: form posts. 404 or otherwise, when I do a form post, I typically drop out of my SES mode and revert back to front-controller / action-variable-based URLs.

As far as the direct byte array file handling, I think we may have touched on this before on some other posts. Like you, I definitely enjoy the fact that many newer tags allow binary variables to be passed-in; there's something that just feels nice about that. As far as the way CF handles the file posting, however, I've personally never found it to be too much of an issue (not to diminish in anyway that it might cause issues for you). I have heard a number of people make comments along the same lines, so it's clearly a valid concern.


Mar 11, 2010 at 12:13 PM // reply »
11 Comments

@Ben

We, finally, have been able to convert all URL and FORM variables inside the framework itself (via getHttpRequestData()). The hardest part was parsing the bytearray sent when a file is uploaded along with other form variables without corrupting the data itself.

As to the bytearray and CF tags. It's not a concern per-se, just more of a feature I wish was available more often. :)


Jul 7, 2010 at 1:14 PM // reply »
20 Comments

I'm using multisite (http://www.hairy-spider.com/post/Multisite.aspx) to run multiple simultaneous websites on my XP machine, and can't find a way to get this to work.... When I add a Virtual Directory to the Default Website in IIS, I still can't see the images. Any thoughts?


Jul 7, 2010 at 1:40 PM // reply »
5 Comments

Do you have "check if file exists" enabled? If so, this will break.

http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/4c840252-fab7-427e-a197-7facb6649106.mspx?mfr=true


Jul 8, 2010 at 10:37 AM // reply »
8,836 Comments

@Eric,

I've only done a small bit of experimenting with getting XP to perform like a "true" server and it was never very straightforward.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Formatting: <strong>bold</strong> <em>italic<em>







  • Help Wanted - Find Your Next ColdFusion Job
Recent Blog Comments
Sep 9, 2010 at 12:50 AM
New ColdFusion Error: Form Entries Incomplete Or Invalid
Once again you save my day Ben. Just migrated from Railo to CF9 and that error was everywhere, I was on the verge of tears... ... read »
Sep 8, 2010 at 7:28 PM
What ColdFusion Teaches Us About The Ultimate "Roll Your Own" Solution
This is how good enterprise software and good enterprise architecture is built. In addition to the time factor and the abstraction potential, the most compelling reason I've ever found to incorporate ... read »
Sep 8, 2010 at 4:47 PM
Ask Ben: Reading In A File Using CFFile And CFInclude
@Ben, Thanks for the quick reply. That was the idea. The getFileFromPath returns a "52648.tmp" file name which is generated by the server not the actual file name. I'm not sure how to extract t ... read »
Sep 8, 2010 at 4:10 PM
Strange ColdFusion URLDecode() and GetEncoding() Behavior
Yep - too strange since the second arg in urldecode is optional. I did run across the error and googled it and landed safely here. Thanks, Ben! ... read »
Sep 8, 2010 at 3:33 PM
What ColdFusion Teaches Us About The Ultimate "Roll Your Own" Solution
@Steve, @Darren, Excellent point! Keeping a platform API (any API at that matter) allows for a much easier time to swap underlying libraries, or even to build your own. @Rick, @Jacob, @JC, I thin ... read »
JC
Sep 8, 2010 at 2:02 PM
What ColdFusion Teaches Us About The Ultimate "Roll Your Own" Solution
@Jacob -- absolutely. The trick is knowing when it'll take less time to do it yourself than wedge someone else's oval shaped application into your round hole. ... read »
Sep 8, 2010 at 1:49 PM
What ColdFusion Teaches Us About The Ultimate "Roll Your Own" Solution
@Rick, I hope this isn't too off topic but, is this true? I've only been programming in the workplace for 4 years. I often look at what others have done and adapt it to my particular needs. Often t ... read »
Sep 8, 2010 at 12:39 PM
ColdFusion CFMailParam's New "Content" Attribute Is Awesome
Ben, Mine is version 8 and tried to download the update but still did not recognized content attribute in cfmailparam. May be I installed a wrong update, so many of them not sure which one I need wit ... read »