Tuesday, August 13, 2013

Coldfusion: Issue with application mappings and expandPath()

This is just a quickie regarding Coldfusion's per-application mappings and what happens when you try to use expandPath() with your mapping.  (Note:  This is under CF9, our company hasn't yet gone to CF10.)

Working in a test file of testSandbox/testFolder/test.cfm, I needed to access a CFC outside my webroot.  I added this to my testProjection/Application.cfc. (Because there's no way to add per-app mappings at runtime (outside of the Application.cfc) that I could find.)
   this.mappings['cfc'] = 'c:\Development\Sandbox\someOtherFolder';

In my testSandbox/testFolder/test.cfm file I had these lines:
  <cfset local.sPath = expandPath('cfc') />
  <cfdirectory action="list" directory="#local.sPath#" name="local.dir" />
  <cfdump var="#local.dir#" />
  <cfdump var="#local.sPath#" />

The query contained no records.  The local.sPath variable showed (an assumed) path of my working directory, with 'cfc' at the end.  I had no testSandbox/testProject/cfc folder!  But I had added a per-app mapping for it!  What gives?!?!

So I looked at our actual code, and noticed that all the mappings had a leading forward slash.  Okay, so I changed the mapping line to:
   this.mappings['/cfc'] = 'c:\Development\Sandbox\someOtherFolder';

...and ran my lines again.  The query was still empty, and the sPath output still showed 'testProject/cfc'!  Next, I edited the .cfm code to also add the leading slash:
  <cfset local.sPath = expandPath('/cfc') />
  <cfdirectory action="list" directory="#local.sPath#" name="local.dir" />
  <cfdump var="#local.dir#" />
  <cfdump var="#local.sPath#" />

NOW I get a list of the files in the actual cfc folder outside my root.   Out of curiosity, I went back and took out the leading slash in the Application.cfc, so back to:
   this.mappings['cfc'] = 'c:\Development\Sandbox\someOtherFolder';

and ran again.  The results were completely different.  This time it pointed to:
   testSandbox/cfc

That sort of makes sense, as it pointed to the [webroot]/cfc and I'm using a leading forward slash, except I kept asking "why isn't the mapping honored?".

Clearly, you have to create the mapping with a leading slash like:
  this.mappings['/cfc'] = ....

....and you have to access it with the leading slash, at least for directory- and file-based operations.  

Running a createObject with just the mapping name (the only way you can):
  <cfset local.marshaller = createObject('component', 'cfc.integrations.Gateway') />

seems to work just fine, whether the Application.cfc this.mappings key has the leading slash or not.  So createObject() seems to treat the value differently than does a file/directory operation.  Again, this is for Coldfusion 9, I haven't tested the behavior on CF10 or Railo yet.

- Will Belden
August 13, 2013

No comments: