When Extending an Application.cfc Through a Root Proxy How Do I Prevent <cfincludes> from Breaking?

723 views Asked by At

I'm in the process of switching over from using Application.cfm to Application.cfc and I'm using Ben Nadel's method for extending my application into a sub folder using an application proxy. (link to article)

The problem I'm having is that when I load a page in a sub folder all cfinclude tags that are called in the root Application.cfc file bring up a "Could not find the included template..." error message. (The include is intentionally at the top of the component so I can set application specific variables)

Here are a few requirements:

  • The application has to be run without access to the ColdFusion administrator.
  • The application may or may not reside in a sub folder of another site (i.e. www.example.com/ or localhost/mysite/)

Here's the file structure:

  • /application.cfc
  • /include_me.cfm
  • /index.cfm
  • /sub/application.cfc
  • /sub/application_rootProxy.cfc
  • /sub/index.cfm

Root Application.cfm:

<cfcomponent
    output="false"
    hint="I define the application settings and event handlers.">
 
 
    <!--- Define the application settings. --->
    <cfset this.name = "TestApplication" />
    <cfset this.applicationTimeout = createTimeSpan( 0, 0, 10, 0 ) />
 
    <!---
        Store the path of the current template. We want to see if
        this shows up as the root template or the sub template.
    --->
    <cfset this.ROOT_currentTemplatePath = getCurrentTemplatePath() />
    
    <!--- Set a variable to indicate that the included file hasn't been run yet --->
    <cfset this.includedFile = "no" />
    
    <!--- include the file --->
    <cfinclude template="include_me.cfm" />
 
    
    <cffunction
        name="onApplicationStart"
        access="public"
        returntype="boolean"
        output="false"
        hint="I initialize the application.">
 
        <!--- Set some app variables for testing. --->
        <cfset application.ROOT_onApplicationStart = true />
 
        <!--- Return true so the page can process. --->
        <cfreturn true />
        
    </cffunction>
 
 
    <cffunction
        name="onRequestStart"
        access="public"
        returntype="boolean"
        output="false"
        hint="I initialize the request.">
 
        <!--- Set some request variables for testing. --->
        <cfset request.ROOT_onRequestStart = true />
 
        <!--- Return true so the page can process. --->
        <cfreturn true />
        
    </cffunction>
 
 
    <cffunction
        name="onRequest"
        access="public"
        returntype="void"
        output="true"
        hint="I process the user's request.">
 
        <!--- Define arguments. --->
        <cfargument name="script"type="string" required="true"hint="I am the request script." />
 
        <!--- Output the current THIS collection. --->
        <cfdump var="#this#" label="THIS" />
 
        <!--- Include (execute) requested script. --->
        <cfinclude template="#arguments.script#" />
 
        <!--- Return out. --->
        <cfreturn />
        
    </cffunction>
 
</cfcomponent>

Root Include_me.cfm:

<!--- update the value so we know the file was indeed included --->
<cfset this.includedFile = "yes" />

Sub Folder Application.cfc

<!--- extends the application so we can make changes when needed --->
<cfcomponent extends="application_rootProxy">
 
 <cfset this.SUB_currentTemplatePath = getCurrentTemplatePath() />

</cfcomponent>

Sub Folder Root Proxy:

<cfinclude template="../application.cfc">

What is the correct way to allow cfinclude tags in the base application.cfc when you're accessing the application through a root proxy?

My initial instinct was to see if I could calculate the application root dynamically and luckily getCurrentTemplatePath() is able to differentiate between the sub application.cfc and the root application.cfc. However cfincludes don't work when you try and access them via a local file system link (e.g. d:\mysite\include_me.cfm). It looks like I need to somehow figure out the dynamic relative position of the included file based on the sub directory of the executing application.cfc. Any and all help is appreciated!

2

There are 2 answers

0
Dave L On

I may be on to something... and if this is the answer hopefully it will help someone else out who finds themselves in a similar predicament.

I noticed that the cfinclude within the OnRequest() method processes normally regardless of whether the template is being called from the root of the application or a sub directory. Therefore I theorized if I put my cfincludes within methods they might execute properly.

So instead of placing my cfincludes at the top of my root component:

<cfcomponent>
    
  <cfinclude="include_me.cfm">
    
  ...

</cfcomponent>

I can put them in a separate method and then call that method within the component:

<cfcomponent>
  
  <!--- call the method which includes the file --->
  <cfset includeFile() />
  
  <!--- new method for including the file --->
  <cffunction name="includeFile">
  
    <cfinclude="include_me.cfm">
    
  </cffunction>

  ...
  
</cfcomponent>

The key to this seems to be not including anything in application.cfc unless it's contained within a method.

8
Adam Cameron On

I'm not sure what's causing what you're seeing, but you do have an unorthodox way of proxying your Application.cfc

This doesn't solve your issue, but here is a demonstration of doing the proxying correctly, and this doesn't have the include pathing issue you're seeing.

All the code is here: https://gist.github.com/daccfml/3ed091c62d688595d66e

/Application.cfc

component {
    writeOutput("#getCurrentTemplatePath()# called<br>");
    include "inc.cfm";
}

/inc.cfm

<cfoutput>#getCurrentTemplatePath()# called<br></cfoutput>

/ApplicationProxy.cfc

component extends="Application" {
    writeOutput("#getCurrentTemplatePath()# called<br>");
}

/sub/Application.cfc

component extends="ApplicationProxy" {
    writeOutput("#getCurrentTemplatePath()# called<br>");
}

/sub/test.cfm

<cfoutput>#getCurrentTemplatePath()# called<br></cfoutput>

This outputs:

C:\wwwroot\Application.cfc called

C:\wwwroot\inc.cfm called

C:\wwwroot\ApplicationProxy.cfc called

C:\wwwroot\sub\Application.cfc called

C:\wwwroot\sub\test.cfm called

Which is what I'd expect.

Rearrange your code to do the proxying correctly, and hopefully your issue will disappear. If not, update your question and we can revisit.