Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to rewrite url using ColdFusion?

I have got a requirement for generating user friendly urls.I am on IIS.

My dynamic URLs looks like,

www.testsite.com/blog/article.cfm?articleid=4432

Client wants the urls should look like

www.testsite.com/blog/article_title

I know this can be easily done using IIS URL rewiter 2.0.

But the Client wants to do it using ColdFusion only. Basic idea he given like,

  1. User will hit the url www.testsite.com/blog/article_title
  2. I need to fetch the article id using the article_title in the url.
  3. Using the ID to call the article.cfm page and load the output into cfsavecontent and then deliver that output to the browser.

But I do not think its possible at application server level. How IIS will understand our user friendly urls . OR am I missing something important? Is it possible to do it using ColdFusion at application server level?

like image 918
Deepak Kumar Padhy Avatar asked Mar 18 '23 14:03

Deepak Kumar Padhy


2 Answers

First, I hate to recommend reinventing the wheel. Webservers do this and do this well.

Cold Fusion can do something like this with #cgi.path_info#. You can jump through some hoops as Adam Tuttle explains here: Can I have 'friendly' url's without a URL rewriter in IIS?.


Option #2: My Favorite: OnMissingTemplate..

Only available to users of Application.cfc (I'm pretty sure .cfm has no counterpart to onMissingTemplate).

You can use this function within application.cfc and all affected pages will throw any "missing" urls at this event. You can then place

<cffunction name="onMissingTemplate">
        <cfargument name="targetPage" type="string" required=true/>
        <!--- Use a try block to catch errors. --->
        <cftry>
                <cfset local.pagename = listlast(cgi.script_name,"/")>
                <cfswitch expression="#listfirst(cgi.script_name,"/")#">
                    <cfcase value="blog">
                        <cfinclude template="mt_blog.cfm">
                        <cfreturn true />
                    </cfcase>
                </cfswitch>
                <cfreturn false />
                <!--- If no match, return false to pass back to default handler. --->
                <cfcatch>
                      <!--- Do some error logging here --->
                      <cfreturn false />
                </cfcatch>
        </cftry>
</cffunction>

mt_blog.cfm can have contents like, if your url is say just like /blog/How-to-train-your-flea-circus.cfm

<!--- get everything after the slash and before the dot --->
<cfset pagename = listfirst(listlast(cgi.script_name,"/"),".")>

<!--- you may probably cache queries blog posts --->
<cfquery name="getblogpost">
  select bBody,bTitle,bID
    from Blog
   where urlname = <cfqueryparam cfsqltype="cf_sql_varchar" value="#pagename#">
</cfquery>

<!--- This assumes you will have a field, ex: urlname, that has a url-friendly format to match
      to. The trouble is that titles are generically, in most blogs, changing every special char
      to - or _, so it's difficult to change them back for this sort of comparison, so an add'l
      db field is probably best. It also makes it a little easier to make sure no two blogs have
      identical (after url-safe-conversion) titles. --->

...

Or if you use a url like /blog/173_How-to-train-your-flea-circus.cfm (where 173 is a post ID)

<!--- get everything after the slash and before the dot --->
<cfset pageID = listfirst(listlast(cgi.script_name,"/"),"_")>

<!--- you may probably cache queries blog posts --->
<cfquery name="getblogpost">
  select bBody,bTitle,bID
    from Blog
   where bID = <cfqueryparam cfsqltype="cf_sql_integer" value="#pageID#">
</cfquery.

...
like image 107
Regular Jo Avatar answered Mar 20 '23 03:03

Regular Jo


I don't recommend using a missing file handler (or CF's onMissingTemplate). Otherwise IIS will return a 404 status code and your page will not be indexed by search engines.

What you need to do is identify a unique prefix pattern you want to use and create a web.config rewrite rule. Example: I sometimes use "/detail_"+id for product detail pages.

You don't need to retain a physical "/blog" sub-directory if you don't want to. Add the following rewrite rule to the web.config file in the web root to accept anything after /blog/ in the URL and interpret it as /?blogtitle=[everythingAfterBlog]. (I've added an additional clause in case you want to continue to support /blog/article.cfm links.)

<rules>
    <rule name="Blog" patternSyntax="ECMAScript" stopProcessing="true">
        <match url="blog/(.*)$" ignoreCase="true" />
        <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
            <add input="{SCRIPT_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{PATH_INFO}" pattern="^.*(blog/article.cfm).*$" negate="true" />
        </conditions>
        <action type="Rewrite" url="/?blogtitle={R:1}" appendQueryString="true" />
    </rule>
</rules>

I recommend using a "301 Redirect" to the new SEO-friendly URL. I also advise using dashes (-) between word fragments and ensure that the character case is consistent (ie, lowercase) or you could get penalized for "duplicate content".

like image 26
James Moberg Avatar answered Mar 20 '23 04:03

James Moberg