Joe asks:
I really like how you did the udf.cfm/NAME on your site. Can you point me to where and how you did this and/or if this is a UDF. Thanks!!!
Joe is talking about the "shorthand" URL tool I built at CFLib.org. It allows for simpler URLs like so: http://www.cflib.org/udf.cfm/isEmail. How is this done?
It's really two parts. First we have to recognize the "weird" URL form - and once we do - we then parse it. The second part is specific to CFLib and I'll only cover it briefly.
To begin with - whenever a URL comes in with the form, http://host/filename.cfm/stuff/at/the/end, your web server will recognize that "filename.cfm" is the file you want. It will then take the "extra" stuff and store it in a CGI variable, path_info. So consider this blog entry. Everything after index.cfm is located in the path_info CGI variable. Sometimes - this CGI variable will also contain the filename. Luckily, Michael Dinowitz wrote a nice little article showing sample regex to "clean" this value. I don't seem to see a "direct" link to his article, but it on the front page at House of Fusion. (Look for the article, "Search Engine Safe (SES) URLs.) In this article he has a full blown UDF for dealing with the values, but I'm going to focus just on the regex. This example below shows it in action:
<cfoutput>
cgi.path_info=#cgi.path_info#<br>
stripped: #pathInfo#
</cfoutput>
You don't have to worry too much about the regex, it basically just handles removing any potential filename from the CGI variable. I'm not seeing any filename on my Apache or IIS server, but I know I've seen it in the past.
At this point we have a pathInfo variable that will store any information that added to the end of our filename. How do we parse this? Obviously you have a ColdFusion list using the / character are a delimiter. In my example above, "http://host/filename/stuff/at/the/end", my pathInfo variable would have: "/stuff/at/the/end". How I parse that is up to the application. In BlogCFC, I check the length of the value (using listLen and / as the delimiter) to make sure the length is 4. The firs three values refer to the date and the last item refers to the alias.
You may want to use a format that is like typical URL variables. Something like: http://host/filename.cfm/product/323. In this form, the URL is simply another way of saying: http://host/filename.cfm?product=323. To parse this form, I would have to loop over the list and set URL variables. Here is a sample that will do that:
var pathInfo = reReplaceNoCase(trim(cgi.path_info), '.+\.cfm/? *', '');
var i = 1;
var lastKey = "";
var value = "";
if(not len(pathInfo)) return;
for(i=1; i lte listLen(pathInfo, "/"); i=i+1) {
value = listGetAt(pathInfo, i, "/");
if(i mod 2 is 0) url[lastKey] = value;
else lastKey = value;
}
//did we end with a "dangler?"
if((i-1) mod 2 is 1) url[lastKey] = "";
return;
}
What are we doing here? As I mentioned before, we begin by looking for stuff after the final slash. If we find nothing, we exit the function. (Normally a UDF returns something. A return statement by itself just means to leave the function without returning anything at all.)
Next we treat the value as a list and loop over it. We want to do things in twos - in other words, the first item is a variable, the second is a value. We simply check our list counter, i, and on odd numbers, we store the value as "lastKey", and on even numbers, we write to the URL scope. (UDFs should never directly access variables outside their own scope. Except when they should. ;) This code assumes an even number of values. So what happens if the pathInfo variable is odd? (Ex: /products/5/foo) We treat this then as a "empty" variable and create the value in the URL scope with an empty string. This could be used as a flag. So for example, /productid/5/short, could mean set url.productid to 5, which is the database record to load, and "short" simply means show the shorthand version of the content.
Comment 1 written by Jack Dalaa on 2 August 2005, at 5:37 PM
RewriteRule (/servlet/.*?)(\?[^/]*)?/([^/]*)/([^/]*)(.+?)? $1(?2$2&:\?)$3=$4?5$5: [N,I]
RewriteRule /servlet(.+?)/?(\?.*)? $1.cfm$2 [I]
(two lines)
Then you can do URL's like:
http://www.mydomain.com/servlet/view/product/super...
Which would then be:
http://www.mydomain.com/view.cfm?product=supercar
.. replace the 'servlet' trigger in the rule with whatever you want.
With a bit of template planning, you can do some seriously snazzy URL's with this.
Comment 2 written by Raymond Camden on 2 August 2005, at 5:45 PM
Comment 3 written by Jake on 2 August 2005, at 9:37 PM
Comment 4 written by HKS on 2 August 2005, at 11:42 PM
The fix is simple enough, you just need to hack web.xml a little. See http://www.doughughes.net/index.cfm/page-blogLink/... for details.
Comment 5 written by justin on 2 August 2005, at 11:48 PM
Anyone have a suggestion on if this is possible to achieve using a method like this?
Comment 6 written by Michael on 3 August 2005, at 1:49 AM
Comment 7 written by Raymond Camden on 3 August 2005, at 7:37 AM
a) In Apache, use mod_rewrite. It's free. It's awesome.
b) In IIS, use ISAPIRewrite. It is free if you use the simple edition. The simple edition applies all rules to all domains on a box. If you only have one site, or only one site using rewriting, then you are fine. However, the "expensive" edition is only 75 dollars. Not bad.
Comment 8 written by Chris Peters on 3 August 2005, at 8:40 AM
I'm guessing at this point that Google and company have caught on to this workaround and consider it to be the same as just using a query string.
Keep in mind that once your site becomes "important" enough, the search engines will start indexing _all_ of your content, query string or no.
Comment 9 written by Raymond Camden on 3 August 2005, at 8:48 AM
Comment 10 written by Jacob Sevlie on 3 August 2005, at 10:02 AM
RewriteRule /servlet(.+?)/?(\?.*)? $1.cfm$2 [I]
Comment 11 written by Jack Dalaa on 3 August 2005, at 10:09 AM
.. I just took one of the existing rules from their documentation (or forum? Don't remember), tweaked it until it worked as I wanted, and left it at that. It's regex far beyond my brain-power. :-)
It's a piece of beauty though, works *great*.
Comment 12 written by erikv on 15 May 2006, at 1:25 PM
Comment 13 written by Ajaxsaur on 19 February 2007, at 11:33 PM
It's possible, and a lot easier, to do this on the Web server level, for example on IIS, using the ISAPI Rewrite product (free version will do!), and a rule like:
RewriteRule (/servlet/.*?)(\?[^/]*)?/([^/]*)/([^/]*)(.+?)? $1(?2$2&:\?)$3=$4?5$5: [N,I]
RewriteRule /servlet(.+?)/?(\?.*)? $1.cfm$2 [I]
(two lines)
Then you can do URL's like:
http://www.mydomain.com/servlet/view/product/super......
Which would then be:
http://www.mydomain.com/view.cfm?product=supercar
.. replace the 'servlet' trigger in the rule with whatever you want.
With a bit of template planning, you can do some seriously snazzy URL's with this.
[/quote]
Logically it would be better for dynamics to do it with CFML rather then server side, because it allows you to organize template systems by database better, rather then relying solely on "cfml", when parsing it with coldfusion you can effectivly reduce the amount of data passed through the URI allowing you to segment out template and variables, its like we do in PHP most of the time when doing SEO URIS. A little bit of regex and database testing or even file testing and you could welp get er done alot more dynamically.
Comment 14 written by Raymond Camden on 20 February 2007, at 7:28 AM
Comment 15 written by Nate on 2 April 2007, at 11:22 AM
<cfif CGI.PATH_INFO DOES NOT CONTAIN ".cfm">
<cfset test = parseSES()>
</cfif>
I'm sure there's a better way than this...
Comment 16 written by Raymond Camden on 2 April 2007, at 11:27 AM
Comment 17 written by Nate on 2 April 2007, at 3:51 PM
http://host/filename.cfm/phrase / with a slash in it/777
Comment 18 written by Raymond Camden on 2 April 2007, at 4:13 PM
Comment 19 written by Nate on 2 April 2007, at 6:10 PM
Here's my code if anyone else is interested:
<cfset newlink = Replace(link,'/','','all') >
<a href="/results.cfm/#tagid#/#newlink#">#link#</a>
Comment 20 written by Seth on 24 April 2007, at 8:43 AM
Comment 21 written by Raymond Camden on 24 April 2007, at 10:44 AM
Comment 22 written by Seth on 24 April 2007, at 11:03 AM
Comment 23 written by Raymond Camden on 24 April 2007, at 11:11 AM
Comment 24 written by Josh Eby on 6 June 2007, at 2:05 PM
Also, is there a link to this UDF on cflib.org at all?
Comment 25 written by Raymond Camden on 6 June 2007, at 2:18 PM
Comment 26 written by Josh Eby on 6 June 2007, at 2:28 PM
An example of what I have used in the past is here:
http://www.cftopper.com/index.cfm?page=blog&bl...
The problem I have is when using relative URLs my url gets added to as you click links...
For Example...
you go to index.cfm/page/5
then you click a link for page 23...
now you are at index.cfm/page/index.cfm/page/23
The request still works, but it defeats the purpose.
The thing that I like about the CFML solution is that the key/value pairs are passed in the URL and you could have a varying number of query items on each page... can you do this with the IIS Re-Write as well?
Comment 27 written by Raymond Camden on 6 June 2007, at 2:35 PM
Comment 28 written by Joost van der Drift on 17 July 2007, at 2:15 AM
I'm wondering: how to handle a site with SES urls in combination with CF administrator. E.g. when I schedule a template in the CF Admin with timeout, the URLs look like
http://www.domain.com/path/to/index.cfm/fuseaction...
And this goes wrong, it should be
http://www.domain.com/path/to/index.cfm/fuseaction...
Comment 29 written by Joost van der Drift on 17 July 2007, at 2:26 AM
I'll try again: CF Administrator creates this
URL when scheduling a page with a timeout
.../index.cfm/fuseaction/dothis?RequestTimout=60
And this goes wrong when using SES Urls.
How to handle this?
Comment 30 written by Raymond Camden on 17 July 2007, at 7:35 AM
The other option is to use cfsetting requesttimeout in the code instead of setting a requesttimeout in the CF Admin for the task.
Comment 31 written by Troy on 20 September 2007, at 3:23 PM
test.com/testing/id/555
this really should be pulling
test.com/testing/index.cfm?id=555
is there away to fix this. reason I'm not using the server level replace is I don't know if this application is going to be on a shared or dedicated server yet.
the error I'm getting is
404
/testing/test/1234
java.io.FileNotFoundException: /testing/test/1234
at jrun.servlet.file.FileServlet.service(FileServlet.java:349)
at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106)
at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:284)
at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543)
at jrun.servlet.http.WebService.invokeRunnable(WebService.java:172)
at jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:320)
at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
at jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:266)
at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)
Comment 32 written by Raymond Camden on 20 September 2007, at 3:28 PM
This blog entry was meant to describe a solution that did not require any web servere mods.
Comment 33 written by Jason on 24 September 2007, at 10:33 AM
Works..
http://mysite.com/index.cfm?fuseaction=app.showFor...
Doesn't work..
http://mysite.com/index.cfm/fuseaction/app.showFor...
I'm running CF8 and Fusebox 5.1.
Comment 34 written by J. on 8 February 2008, at 2:47 AM
Did some experiments:
- cfform type="flash" doesn't work
- cfform type="html" does work
- cfchart works
- cftextarea also works
The CFIDE Virtual Directory does exist but no flash forms
Any suggestions?
Flash Form that would not load the movie got a wrong path I think:
src='/ict/jvl/mod_rewrite/1799017575.mxml.cfswf'
But if I'm viewing it directly it works:
src='/ict/jvl/mod_rewrite/content/services/ce/information/index.cfm?ID=2005'
Comment 35 written by glieu on 27 March 2008, at 10:14 PM
I am a newbee to Coldfusion. i am trying to understand your blogCFC 5 i downloaded. How did you hide the blog id create with CreateUID() function?
You have something like http://www.domain.com/index.cfm/2008/03/27/some-bo... , how did you translate /2008/03/27/some-blog-title back to blog id and get the details for some-blog-title?
Please help.
Thank you
Comment 36 written by Raymond Camden on 28 March 2008, at 8:44 AM
I then make links with the date plus the alias, which you have to assume is unique. WHen you view the entry, I just look up based on alias+date.
Comment 37 written by glieu on 1 April 2008, at 10:01 PM
I try it, it works. Another question, instead of this
www.domain.com/index.cfm/2008/04/01/blog-title
if I want to achieve this,
www.domain.com/2008/04/01/blog-title or
www.domain.com/blog/2008/04/01/blog-title
How would I do it?
Please help.
Many thanks.
Comment 38 written by Raymond Camden on 2 April 2008, at 5:56 AM
Comment 39 written by Jack D on 2 April 2008, at 6:28 AM
Comment 40 written by Raymond Camden on 2 April 2008, at 6:29 AM
Comment 41 written by Derek Versteegen on 8 April 2008, at 7:33 AM
I'm trying to introduce the use of SEF URLs on this site and have been very successful doing so. Its help a ton as I've been able to build some very much needed redirect applications that get users into certain areas faster. But my problem is similar to several other listed already that appear to not have been resolved - unless I missed something.
It is the flash form problem,
Works:
...roster-edit.cfm?action=update&id=123456
Doesn't Work:
...roster-edit.cfm/action/update/id/123456
Just by swapping out the characters in the URL I can get the form to load. But when I introduce the SEF link naming convention into the site (meaning once I code links the SEF way) all my flash forms that are dependent on a URL parameter break.
Did I miss the solution here somewhere? Coudl someone share it again, please?
P.S. I do not have access to the CF Admin or IIS - I have to do this all in code (shared server).
Thanks in advance.
Comment 42 written by Derek Versteegen on 8 April 2008, at 8:16 AM
<cfscript>
pathInfo = reReplaceNoCase(trim(cgi.path_info), '.+\.cfm/? *', '');
i = 1;
lastKey = "";
value = "";
if(not len(pathInfo)) break;
for(i=1; i lte listLen(pathInfo, "/"); i=i+1) {
value = listGetAt(pathInfo, i, "/");
if(i mod 2 is 0) url[lastKey] = value;
else lastKey = value;
}
break;
</cfscript>
do introduce SEF URLs. As I mentioned that was successful but it broke my flash forms.
Before I make my next point, I should let you know that I version my cfapplication names so that I can reset applications and have CFadmin essentially create new application logs for me to compare should I need to.
So, I found it odd when I went back into the Application.cfm file and simply removed that same code (without renaming my cfapplication name). I loaded the form page and it errored out. When I reintroduced that code and saved my Application.cfm file, the refresh of the form loaded the flash form correctly.
I *think* I know why this happened and I am wary that it might not last so I am watching it closely. I have my test and development environments to try this out on too.
Comment 43 written by Raymond Camden on 8 April 2008, at 8:20 AM
Comment 44 written by Derek Versteegen on 9 April 2008, at 9:15 AM
a.) I have a link to a page that edits a user record via flash form
b.) the link is coded with traditional question mark, equal and ampersand signs for the query string.
c.) having introduced the SEF script, when the page loads I can see the request actually changing from the old format to the new format.
d.) the reason why I see it change is because I have a SSL redirect script in place to ensure the page is loaded and processed using SSL. Since the original request is being made from a non-secure page, my redirect script now rewrites URLs using the SEF format.
e.) If I take the URL it redirects to (the SEF one) after the page is done loading (with no visible flash form) then replace the characters manually with traditional format (for example: ...-action.cfm/userid/123 to ...-action.cfm?userid=123) the flash form loads fine.
f.) I've modified the page that offers the link to the form by prefixing the anchor with my secure url application variable instead of solely relying on the page requested to determine it was not being loaded in an SSL - I still have that code there of course.
So, the issue is bandaided in the respect that I've tracked down the links that point tot he page and have made sure the links to the page are build with SSL. And if someone were to decided to change the SSL to a regular http request at least there is comfort knowing the page will not load. But it still leaves me to with having to look at my SSL redirect page to see if I need to do something there (which I can't imagine I need to since it does its job nicely).
Therefore, this leads me (finally) to answering your question . . . there is no difference between the rendered source code of the form when it doesn't load and when it does - other than the swf cacheid.
So by changing manually reverting the URL from SEF to traditional, then back to SEF everything works. But as its taken me 30 min. to write this post and double check everything, I am faced with starting my troubleshooting issue all over since FF and IE seem to be doing things differently.
I think its a client side issue because I have plenty of other flash forms that have not been affected by this. However, all the other flash forms that do work do not have URL query strings being re-imagined into a SEF url format.
(sorry for the lengthy posts - this is just really boggling me - all the a flash forms work until they happen to be on a page that uses SEF url formatting.)
Comment 45 written by Luc on 6 June 2008, at 5:11 PM
Comment 46 written by Microcycles on 18 August 2008, at 11:11 PM
Comment 47 written by JB on 11 January 2009, at 4:04 PM
a.com/var/value/value.cfm
Comment 48 written by Matthew on 18 February 2010, at 5:36 PM
so how would you get it to pull the values for the cleanURL from a a database? (so that you could set any value at anytime for a particular page)
Comment 49 written by Raymond Camden on 19 February 2010, at 2:28 PM
page.cfm/X
then you store X in the database or generate it when you make your links.
Comment 50 written by Matthew on 21 February 2010, at 2:28 AM
yes, the link would be a simple page.cfm/article format.
Comment 51 written by Raymond Camden on 21 February 2010, at 10:39 AM
Did that answer your question?
[Add Comment] [Subscribe to Comments]