ExpandPath() Works With ColdFusion's Per-Application Mappings
I don't use ColdFusion's expandPath() function very much. Sure, I'll use it in a demo when I want to just "get it done;" but, I rarely use it in any production code. I don't completely understand how expandPath() works, which has lead to invalid file paths and broken sites. That said, I'm trying to learn more about the expandPath() function; and, I'm pretty excited to find out that it works well with ColdFusion's per-application mappings.
In the past, I've used the expandPath() function almost exclusively with relative file paths which were relative to the current URL. This means that a single expandPath() expression (in the Application.cfc file, for example) can have a different outcome depending on which URL is currently being accessed. This is typically why I don't use expandPath() in production.
As of ColdFusion MX, however, the expandPath() function can accept absolute URLs. And this is where the per-application mappings come into play. expandPath() will resolve paths using mappings defined within the Application.cfc ColdFusion framework components.
To test this, I created a few mappings in my Application.cfc file:
<cfscript>
component
output = false
hint = "I define the application settings and event handlers."
{
// Define the application settings.
this.name = hash( getCurrentTemplatePath() );
this.applicationTimeout = createTimeSpan( 0, 0, 5, 0 );
// Configure the mappings. Notethat Bar is a sub-directory of
// Foo, which is a subdirectory of App.
this.directory = getDirectoryFromPath( getCurrentTemplatePath() );
this.mappings[ "/app" ] = this.directory;
this.mappings[ "/foo" ] = "#this.directory#foo/";
this.mappings[ "/bar" ] = "#this.directory#foo/bar/";
// No matter what CFM file is requested, inlucde the root index.
public void function onRequest( required string template ) {
include "./index.cfm";
}
}
</cfscript>
Then, I accessed the following file from a "sub/sub/" directory:
<cfoutput>
Expand Relative:<br /> #expandPath( "~.htm" )#<br />
<br />
Expand App:<br /> #expandPath( "/app/~.htm" )#<br />
<br />
Expand Foo:<br /> #expandPath( "/foo/~.htm" )#<br />
<br />
Expand Bar:<br /> #expandPath( "/bar/~.htm" )#<br />
<br />
Expand Root:<br /> #expandPath( "/~.htm" )#<br />
<br />
</cfoutput>
My web-application is located at the following file system location:
**/Sites/bennadel.com/testing/expand-path/**Application.cfc
... and when I access the above index file (via, the "sub/sub/" directory), I get the following page output:
Expand Relative:
/Sites/bennadel.com/testing/expand-path/sub/sub/~.htmExpand App:
/Sites/bennadel.com/testing/expand-path/~.htmExpand Foo:
/Sites/bennadel.com/testing/expand-path/foo/~.htmExpand Bar:
/Sites/bennadel.com/testing/expand-path/foo/bar/~.htmExpand Root:
/Sites/bennadel.com/~.htm
As you can see, the expandPath() function correctly resolved the absolute paths defined by the ColdFusion per-application mappings, "/app", "/foo", and "/bar". The relative file path (the first example) continues to resolve relative to the current "sub/sub/" URL.
NOTE: Notice that resolving the "/" path in the last example resolved to the root of my Apache VirtualHost entry. I would avoid using the "/" path without a per-application mapping as I believe that I've seen this behave inconsistently across different J2EE servers. I'm on JRUN.
The fact that expandPath() works well with ColdFusion's per-application mappings definitely makes me feel differently about using expandPath() in production! That said, I would still avoid using it in the Application.cfc pseudo-constructor as the per-application mappings don't take effect until you get into the ColdFusion application event handlers (ex, onApplicationStart, onRequestStart).
Want to use code from this post? Check out the license.
Reader Comments
One thing to be careful about expand path is, it doesn't work if the file or directory doesn't exist. It doesn't throw error, but it returns wrong path. So, something like this fileExits(expandPath('/mydir/myfile')) may or may not work.
What surprises me the most is it works with IIS's virtual directory as well!
@Sumit,
That sound scary :)
@Henry,
I'd be careful there, I *believe* the documentation says that it may be funky with virtual directories:
This function does not reliably use virtual mappings that are defined in IIS, Apache, or other web servers.
I don't know very much about servers and how they work; so just be careful :)
@All,
As a follow-up, here's a quick demo of using the per-application mappings with expandPath() in the context of file-io:
www.bennadel.com/blog/2526-Using-Per-Application-Mappings-With-File-I-O-In-ColdFusion.htm
I can see this being super useful!