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

Posted March 5, 2010 at 9:38 AM by Ben Nadel

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 »
10,640 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 »
10,640 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 »
10,640 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 »
28 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 »
10,640 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.


Jun 17, 2011 at 6:22 AM // reply »
1 Comments

if I use Apache. is it same the script like this :
RewriteCond %{REQUEST_URI} !(?i)^[\\/]CFFileServlet


Sep 28, 2011 at 10:51 PM // reply »
1 Comments

I have added a rule to convert all to lower case in IIS7 and the cfimage not displaying how can I add the rule for IIS7 Thank you



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:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Feb 10, 2012 at 7:21 PM
jQuery AJAX Strips Script Tags And Inserts Them After Parent-Most Elements
Update! Instead of $(eval(options.insertAfter)).after(data['insertData']); I now use: var ajaxNode = document.createElement('span'); var parent = $(eval(options.insertAfter))[0].parentNode; ... read »
Feb 10, 2012 at 6:18 PM
jQuery AJAX Strips Script Tags And Inserts Them After Parent-Most Elements
encountered this same, what I consider, jQuery bug last week. I'm building a site in which I load some content via AJAX. This content contains Linkedin share button placeholders which Linkedin API ne ... read »
Feb 10, 2012 at 11:30 AM
Cross-Origin Resource Sharing (CORS) AJAX Requests Between jQuery And Node.js
After you understand the concepts here, this is an awesome cheatsheet for enabling CORS in just about anything http://enable-cors.org/ ... read »
JM
Feb 10, 2012 at 9:10 AM
My Safari Browser SQLite Database Hello World Example
@Amy, Here is a very good tutorial on how to use JOIN: http://www.sqltutorial.org/sqljoin-innerjoin.aspx ... read »
Feb 10, 2012 at 4:42 AM
Building A Twitter-Inspired RESTful API Architecture In ColdFusion
This is great, very useful Ben. I spotted a small typo in the api.cgm listing: <cfthrow type="Unauthroized" /> Cheers Stefan ... read »
Feb 9, 2012 at 10:35 PM
CFDirectory Filtering Uses Pipe Character For Multiple Filters (Thanks Steve Withington)
I was wondering if there would be a filter you could apply so that you got everything but what you included in the filter. As in show me all docs that are not a .pdf. ... read »
Feb 9, 2012 at 10:29 PM
Learning ColdFusion 9: Application-Specific Data Sources
@Ben, No offence, but if people were really wanting advanced features they would be using a platform like ASP.NET MVC. CFML is so structurally compromised as a tag-based scripting language that ... read »
Feb 9, 2012 at 10:03 PM
Subversion - Cleanup Failed To Process The Following Paths
@Leviaguirre, do you still have problems with this? ... read »