Using ColdFusion's CFLocation Tag For Inline Image SRC Attributes

Posted May 17, 2007 at 2:50 PM

Tags: ColdFusion

Not so long ago, I discovered that you could use ColdFusion's CFLocation tag in conjunction with inline image tag SRC attributes. I actually found this out by accident. Before hand, I would have never assumed that this would work. The idea here is that the SRC attribute points to a proxy page which then CFLocates the request on to the actual image file. How does this work? No idea... as far as I am concerned, it's just some crazy voodoo browser request magic.

To help explain what I am talking about, take a look at this HTML page:

 Launch code in new window » Download code as text file »

  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <html>
  • <head>
  • <title>ColdFusion CFLocation And Image Soures</title>
  • <style type="text/css">
  • body {
  • font: 12px georgia ;
  • }
  • </style>
  • </head>
  • <body>
  •  
  • <p>
  • Hey dude, you gotta check out the photo of
  • this chick that I found:
  • </p>
  •  
  • <p>
  • <!--- NOTE: Image proxy. --->
  • <img
  • src="image_proxy.cfm?id=1"
  • width="316"
  • height="217"
  • border="0"
  • />
  • </p>
  •  
  • <p>
  • She's a bit thick, but I think it goes to
  • show that woman of all shapes and sizes can
  • be smokin' hot!
  • </p>
  •  
  • </body>
  • </html>

Notice that the SRC attribute of the IMG tag points to image_proxy.cfm ColdFusion template, not to an actual, physical image file. Now, if the image_proxy.cfm template used CFContent to return an image binary, that would make sense to me; but, as you will see, the image_proxy.cfm template simply forwards the request to the image file:

 Launch code in new window » Download code as text file »

  • <!--- Kill extra output. --->
  • <cfsilent>
  •  
  • <!--- Param the image ID that will be coming in. --->
  • <cfparam
  • name="URL.id"
  • type="string"
  • default=""
  • />
  •  
  •  
  • <!---
  • Check the ID to see if this is a valid photo ID
  • request. If it is, we are going to set the target
  • URL so that we only need ONE CFLocation tag.
  • --->
  • <cfswitch expression="#URL.id#">
  • <cfcase value="1">
  • <cfset strURL = "thick_chick_still_a_hottie.jpg" />
  • </cfcase>
  • <cfdefaultcase>
  • <cfset strURL = "image_not_found.gif" />
  • </cfdefaultcase>
  • </cfswitch>
  •  
  •  
  • <!---
  • ASSERT: At this point, even if we were given an
  • invalid image ID, we are going to have a target URL
  • thanks to the CFDefaultCase tag.
  • --->
  •  
  • <!--- Forward image request to actual image file. --->
  • <cflocation
  • url="#strURL#"
  • addtoken="false"
  • />
  •  
  • </cfsilent>

Again, notice that ColdFusion is not really dealing with the images directly; it's just forwarding the browser's request on to the image. Now, the ColdFusion CFLocation tag actually sends a header value back to the browser which means that the IMG tag loads a page, which returns a header, which then forwards the request to the image.

Not sure how that works, but it does:


 
 
 

 
CFLocation For Use With Inline IMG tag SRC Attributes  
 
 
 

Pretty cool, eh? This could be really cool if you don't have a fancy image database or anything, but you don't want the image location fixed. You could set up a proxy that then knows where the image directory is and can forward appropriately.

Download Code Snippet ZIP File

Comments (15)  |  Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page




Adobe ColdFusion 8.0.1 Update - Helping Programmers To Be Signifanctly Less Girlie - Download ColdFusion 8 Update 8.0.1 Now.

Reader Comments

Not much mystery here - HTTP is a very simple protocol - a GET is a GET, whether it's triggered by typing a URL, or a IMG SRC attribute - the browser fetches it in exactly the same way, and as long as the final result to the browser is something it expects, it will work fine.

This is a really handy tip though - even though it makes perfect sense that it works, it hadn't ever occurred to me to try this...

Posted by Doug Bezona on May 17, 2007 at 3:15 PM


@Doug,

I understand that the HTTP request protocol is very simple. I guess what makes it hard for me (mental visualization) is that when you request a page, no problem, it the primary request... but then on the page it has to load various other things like SCRIPT tags and IMG tags... those are like sub-requests that can then interact with the returned headers.

I guess I can't think of it as a single page request - it's really multiple data requests that the browser then merges (ie. putting in image content into a different request data set). Just seems funky to think about. I get it, just seems funky.

Glad you find it a good tip though.

Posted by Ben Nadel on May 17, 2007 at 3:20 PM


One particular situation I use this mechanism for quite frequently is generating and caching dynamic content. To follow the image theme, if you want to generate thumbnails for your photo gallery, you point your thumbnails at tn.cfm?id=1234, which then gets the full-size image, shrinks it, writes it to cache storage, and redirects to the cache file. Subsequent requests can check for existence of the cache file, and if it's already there, just redirect directly.

I actually use mod_rewrite to do that (which saves the extra HTTP roundtrip), but the concept is the same. Managing the cache is a snap too, just delete the cache file and it'll be regenerated on next request. If you name you cache files intelligently, you can create very granular caching mechanisms for dynamic content, but (if you're using mod_rewrite) serve it in a 100% static way, without involving the app server in any way.

Posted by Barney on May 17, 2007 at 3:30 PM


@Barney,

Good suggestion. I like the idea of the thumbnail generation (but more so, the cache idea in general). Thanks. Caching is something that I don't do enough of (my poor server!).

Posted by Ben Nadel on May 17, 2007 at 3:34 PM


@Ben

Oh, I understand - it's not necessarily intuitive, but when you look as http log files it's pretty clear that, under the hood, all the requests are really the same, and that it's the browser that molds it all together into the proper context.

The only reason I am underscoring the point is this is something that a lot of people seem to not quite "get", and I've just seen a couple of examples of it in the last few days.

Posted by Doug Bezona on May 17, 2007 at 7:49 PM


Ben, there's another use: track visualizations in e-mails.

You can use a image inside the e-mail, via <img src=""> pointing to a ColdFusion page, passing URL parameters to identify which user openned and correctly visualized the e-mail.

BTW, your blog became obligatory nowadays!

Best wishes,

Fernando S. Trevisan

Posted by Fernando S. Trevisan on May 17, 2007 at 7:57 PM


Fernando, et. all

I recently wrote an email tracker as part of a CRM system using this trick not too long ago. Unfortunately, Outlook doesn't automatically download the image so tracking only occurs when the image is downloaded. Do you know of anyway to force the image to download, so tracking work regardless..??

Posted by Alan Johnson on May 17, 2007 at 10:57 PM


Many (most?) email clients don't automatically download images for exactly this reason. It's a rather devious mechanism from the perspective of non-techie users, and as such, should be frowned upon. Therefore, clients disable it by default.

If you need to include images in emails, much better to inline the images. Makes the email bigger, and removes the ability to [sneakily] track reads, but it's a trusted method for getting image content in front of users.

Posted by Barney on May 18, 2007 at 1:51 AM


Ben, what's the advantage of using the cflocation over the cfcontent? The code is slightly neater, but apart from that I don't see any difference in how the image is served.

Posted by duncan on May 18, 2007 at 5:19 AM


Alan,

As far as I know, there's no way to track which user received the e-mail, even when using "request read receipt", user has the right to answer yes or no. As I said in my comment, this is a way to track which user correctly visualized your e-mail; if you send it as a full image, the only way user can see the contents is downloading the image and then... :)

Barney,

I agree with you, but there's a lot of good reasons to use this type of verification. In a intranet, you can send reports to users and then scheduled warnings for those who doesn't correctly visualized it. And it's just a dummy example.

Posted by Fernando S. Trevisan on May 18, 2007 at 5:47 AM


@Fernando,

Firstly, thanks for the kind words. I am glad you appreciate the stuff that I do. Secondly, I think what you are referring to actually has a name. I think it's called an "email bug", but that may have been something someone just told me in passing.

I heard somewhere that while email clients do not automatically download images, more often, they will download external style sheet links. I assume you could do the same thing with the URL and tracking.

@Duncan,

The advantage of using CFLocation over CFContent is one of speed. If you use CFContent, then ColdFusion has to set aside a thread that takes care of reading in the binary and streaming it to the client. While it can do this, it is SLOOOOOW. If you use CFLocation instead, then IIS (in my case) takes care of streaming the file to the browser and it is much faster.

The downside is that CFLocation must use web-accessible URLs where as CFContent can use private directory access. But there are work arounds for that.

Posted by Ben Nadel on May 18, 2007 at 7:12 AM


@Fernando

I experimented with using a full image in an email, this wasn't to track anything, the clients design was just so crazy i didn't want to slice it. One problem i found though while testing was that it often went into my spam folder, especially in gmail, Outlook and Hotmail. Do you know how to get around that?

-Si

Posted by Simon Free on May 20, 2007 at 10:36 PM


I've used to insert text relative to the e-mail, but with the background color and 1px size. But it was a long time ago, I don't know if this still work.

Posted by Fernando S. Trevisan on May 21, 2007 at 9:35 PM


I've been pondering the same question too. Why does some email go into Junk folders while other does not.

I'd also be interested in anyone's thoughts on this. Is it a ratio of text to images? An unsubscribe line?, how the images are handled within an email? Simpicity of the email, or complexity? I've lightly experimented with this a little today. But if anyone has some knowldege on this, it'd be desirable to know from a best practice sort of thing.

Posted by Alan Johnson on May 21, 2007 at 11:46 PM


Alan,

There are a pile of rules that are used. Best bet is to get access to an email account that has visibility into it's spam filtering. SpamAssassin is one that I've used, and it'll send you a nice report about each message that it tagged as spam, with a breakdown of what factors influenced it's decision. High HTML-to-text ratio is one factor that I recall being a significant detriment to a given message's spam score.

Posted by Barney on May 22, 2007 at 2:10 AM


Post Comment  |  Ask Ben


Home   |   Web Log   |   ColdFusion   |   Projects   |   Resume   |   Job Form   |   Search   |   Contact
Epicenter Consulting - Custom Software Solutions for Business Evolution HostMySite.com - The Leader In ColdFusion Hosting