Apache RewriteRule for Changing Your Permalink Settings

I recently updated my blog’s permalink settings and did away with the year and month in the url structure. I’m experimenting with placing the post name more prominently in the url as it is better for SEO.
Here’s the Apache rewrite rule I used to move my blog posts from /yyyy/mm/post-name to /post-name. The rewrite rule uses a 301 redirect so this should not negatively affect the post’s Google rankings.

# Redirect moved blog posts
RewriteBase /blog/
RewriteRule ^20[0-1][0-9]/[0-9][0-9]/(.*) $1 [R=301,L]

Breaking the RegEx apart:

RewriteBase /blog/
This tells the rewrite engine that we are only going to look at URLs that are under the /blog/ directory

^20[0-1][0-9]/
Since we indicated our RewriteBase is “/blog/” on the previous line, “/blog/” will be chopped off of the URLs;
“^” says that our string should now start with the following pattern
I started this blog in 2009, so I only need to target years after 2000. I started my year RegEx with “20” to simplify.
“[0-1]” indicates I’m looking for a number range between zero and one. Since I only need to target between 2009-2013 the next digit could only be a zero or 1.
“[0-9]” indicates that the last digit in the year could be any of these.
“/” the next character should be a forward slash

[0-9][0-9]/
This RegEx targets the months: any digit zero through nine, followed by any digit zero through nine
“/” the next character should be a forward slash

(.*)
The rest of the url is our post-name. “(.*)” says take the rest of the url string and remember it as the first variable.

 $1 [R=301,L]
“$1” is the first variable that we got from the (.*) statement above. “R=301” says to 301 redirect this request to whatever url is in the $1 variable. It knows to prepend ‘/blog/’ to the request because we indicated our URLs should start with “/blog/” using the RewriteBase command. “L” indicates that this should be the Last rewrite rule it processes.

Regex can be confusing. Its is often easiest to build up your RegEx bit by bit until you have the completed statement.

Advertisements

WEB-INFcftagsMETA-INFtaglib.cftld (The system cannot find the path specified)

Recently I moved a long running process inside a cfthread and began to get this error during testing: “WEB-INFcftagsMETA-INFtaglib.cftld (The system cannot find the path specified)”

The issue is that getPageContext().getServletContext().getRealPath(“/WEB-INF”) returns the incorrect path when inside a cfthread.

If you use cfthread you may eventually run into this bug, but maybe not as I think its a very rare bug. There doesn’t seem to be a fix for this issue, at least not in CF9, but I did find a workaround.

A demonstration of the bug






    
    
    

The results:

C:ColdFusion9wwwrootWEB-INF
C:wwwrootWEB-INF

Inside the cfthread Coldfusion has forgotten where /WEB-INF is!

In my case I had:


in the code inside the cfthread.
“New Query()” corresponds with the custom tag C:ColdFusion9CustomTagscomadobecoldfusionquery.cfc.
Query.cfc extends C:ColdFusion9CustomTagscomadobecoldfusionbase.cfc.

To create this object Coldfusion calls “getSupportedTagAttributes” in base.cfc which looks up the attributes in taglib.cftld. That file is located under the /WEB-INF directory. If we dig into the guts of base.cfc we find the offending code is on line 228. Coldfusion tries to find “/WEB-INF/cftags/META-INF/taglib.cftld” but since we are inside a cfthread the code fails to use the correct path.

Creating a mapping didn’t help and neither did creating a virtual directory in Apache.

The workaround

Code similar to this was working fine in the production environment, but how was it avoiding this error? The solution was found when I stepped back and read the entire function. Wrapping the offending line is the code:

if(not isdefined("server.coldfusion.serviceTagAttributes.#tagName#"))

Coldfusion will look up the attributes only if they are not already cached in server memory. This is why this bug is hardly seen: normally all these attributes have been cached before being encountered inside a cfthread. My testing was very specific and so the Query attributes were never loaded prior to entering the cfthread. The trick is to make sure the attributes are cached before entering the cfthread.

For testing I added the line:


before entering the cfthread and that forced the attributes to be cached and the error went away.

I hope this post helps someone else with this issue!

The method matches was not found in component:Ensure that the method is defined, and that it is spelled correctly.

I recently updated my local CF build to 9.0.2. After installation I reloaded my app and everything worked fine. I then went back into the admin and enabled robust exceptions and a few other things for my dev environment. I also saw an option to turn off CFC type check. I had never tried this before so I turned it on to see if there was a speed difference. Instead my app stopped loading and displayed this error:

“The method matches was not found in component C:/wwwroot/MyApp/myComponent.cfc .:Ensure that the method is defined, and that it is spelled correctly.”

Digging into the code, the issue is inside Coldspring. “Matches” is a function used by Coldspring in the ProxyFactoryBean.cfc. With CFC type check turned off it seems that Coldfusion can no longer follow the CFC inheritance and does not realize that this function exists. Turning CFC Type check back off in the CF admin solved the issue, though I am still unsure why this was a problem.

The only other info I found on this issue was this Google Groups thread.

cftag2cfscript – The cftag to cfscript converter for Coldfusion

Just uploaded my new project cftag2cfscript to github this morning.

With the arrival of Coldfusion 9 we can finally build our cfcs in cfscript. I’ve found that there can be a significant speed increase when converting an existing tag based cfc to cfscript. YMMV of course. Others may want to convert legacy cfcs to cfscript because they prefer writing in cfscript. Whatever your reason is for wanting to convert cf tags in to script cftag2cfscript is here to help.

Converting tag-based CF to script based CF is time consuming. This project aims to make it dead simple. Its not there yet, but maybe with your help we can reach that goal.

Checkout cftag2cfscript on Github

A difference between cfloop and for loop in cfscript

I am moving key parts of a codebase to cfscript to take advantage of the speed boost that comes with using cfscript. Along the way I’m discovering the differences between tag-based Coldfusion and cfscript.

Today this was the bug I worked out:

This code will delete 10 widgets:




 

This cfscript will only delete 5 widgets:

var i = 1;
setNumberofWidgets(10);
for(i=1;i<=getWidgetTotal();i++)
{
deleteAWidget();
}

This is because getWidgetTotal() will be called on each iteration of the loop. After deleting 5 widgets the loop will exit because there will only be 5 widgets left and i will equal 5. The cfloop tag from the first example will only evaluate once before starting the loop.

This cfscript will delete 10 widgets:

var i = 1;
var total = getWidgetTotal();
setNumberofWidgets(10);
for(i=1;i<=total;i++)
{
deleteAWidget();
}

By calling the function before starting the loop we can get the total number of widgets and are then able to complete the loop.