Getting the URL/web folder path in ColdFusion
Raymond Camden blogged about a question someone had about getting the folder path for the current template. While Raymond addressed how to get the OS path, how would you get the URL path? So, if you had your user was on the URL http://www.example.com/some/folder/and/file.cfm, how would you go about getting the "/some/folder/and/" path?
While there are always many ways to solve a problem, I've tried to come up with a solution that should work for any version of ColdFusion from 6.0 and above. I wanted to avoid using CGI variables (since those vary by webserver,) so I went with using getPageContext() instead.
Here's the solution I wiped up:
<cfargument name="url" required="false" default="#getPageContext().getRequest().getRequestURI()#" hint="Defaults to the current path_info" />
<cfargument name="ext" required="false" default="\.(cfml?.*|html?.*|[^.]+)" hint="Define the regex to find the extension. The default will work in most cases, unless you have really funky urls like: /folder/file.cfm/extra.path/info" />
<!---// trim the path to be safe //--->
<cfset var sPath = trim(arguments.url) />
<!---// find the where the filename starts (should be the last wherever the last period (".") is) //--->
<cfset var sEndDir = reFind("/[^/]+#arguments.ext#$", sPath) />
<cfreturn left(sPath, sEndDir) />
</cffunction>
If you just call getWebPath() it will return the current web folder path for the current base template.
We use a regular expression to strip out additional path info information that can sometimes be present for people using SEO-friendly URLs. For example, the URLs on my site appear like: http://blog.pengoworks.com/index.cfm/2006/9/27/CFMX-UDF-Parsing-a-URI-into-a-struct which returns a path of /index.cfm/2006/9/27/CFMX-UDF-Parsing-a-URI-into-a-struct. We need the regex to find the last period in the string and assume everything else is additional path info. The default regex should work in the vast majority of cases, but you can adjust it for the corner cases.
You can also manually supply a path such as: #getWebPath('/index.cfm/2006/9/27/CFMX-UDF-Parsing-a-URI-into-a-struct')#. This would return "/" as the web path.
Anyway, hopefully some of you will find this little UDF useful.
Comments
Glad that helped you!
It wasn't exactly what I needed but I got the idea to use getPageContext().getRequest().getRequestURI() from you.
Finally I think I have nailed a function to get the CurrentURL is all scenarios including sub folders etc. Heres the code:
<cffunction name="GetCurrentURL" output="No" access="public">
<cfset var theURL = "http">
<cfif (cgi.https EQ "on" )><cfset theURL = "https"></cfif>
<cfset theURL = theURL & "://#cgi.server_name#">
<cfif cgi.server_port IS NOT 80 AND CGI.server_port IS NOT 443>
<cfset theURL = theURL & ":#cgi.server_port#">
</cfif>
<cfset theURL = theURL & getPageContext().getRequest().getRequestURI()>
<cfif len(cgi.query_string)><cfset theURL = theURL & "?#cgi.query_string#"></cfif>
<cfreturn theURL>
</cffunction>
Just remember that CGI variables vary by web server--which is why I try not to rely on them to much. If you're dealing with an application that's in a very controlled environment it's usually not an issue, but it's something you always want to keep in the back of your mind.
15 minutes after I posted the code above I rewrote the function. Here is a version that will work everywhere and doesn't reply on the CGI vars:
<cffunction name="GetCurrentURL" output="No" access="public">
<cfset var theURL = getPageContext().getRequest().GetRequestUrl()>
<cfif len( CGI.query_string )><cfset theURL = theURL & "?" & CGI.query_string></cfif>
<cfreturn theURL>
</cffunction>
Sweet sweet code. :)
I must admit I got the idea to use the underlying java from Ben Nadel.
Why not stick with getPageContext().getRequest(), this time for the getPathInfo() method, and use it to remove the junk at the end of the URI?
My thought is to replace the last 2 lines of the function with this one:
<cfreturn getDirectoryFromPath(left(sPath, len(sPath) - len(getPageContext().getRequest().getPathInfo()))) />
That works provided you're only examining the current URL. It doesn't work if you need to try and get the root from an arbitrary URL:
getWebPath2('/index.cfm/2006/9/27/CFMX-UDF-Parsing-a-URI-into-a-struct')
I wanted to write a solution that could parse URLs outside of the current context.
trim(getDirectoryFromPath(left(sPath, len(sPath) - len(getPageContext().getRequest().getPathInfo()))))
