[coldbox 3.7] Is there a pre Routes Interceptor?

is there an interception point before the routes are processed?

I am trying to setup some basic CMS capabilities in an application. I currently have an interceptor at ‘preEvent’ which checks the cgi.path_info to see if there is a page in the DB with a matching slug:

`

public void function preEvent(required event, required interceptData){

rc = event.getCollection();

var slug = cgi.path_info;

var page = getPageBySlug(slug);

if (!isNull(page)){

event.setView(‘cms/page’;

rc.cmscontent = page;

}

}

`

This works fine on it’s own… however… If there is NO matching page, I would like the process to continue as normal. But when I setup a standard handle/action route…

addRoute(pattern=":handler/:action");

… I receive an error that an event doesn’t exist if I pass in a slug on the path info. So I guess the routes are being rendered before the ‘preEvent’ interceptor.

So… I guess if I can get this interceptor to run before the routes are processed… it ‘should’ work fine.

To quickly recap the flow I am trying to achieve:

  1. Using an interceptor, check if there is a page in the DB with a slug that matches the cgi.path_info.

  2. If yes, process and render that page.

  3. If no, just continue on with the normal CB application flow (processing handlers and actions etc…)

Can anyone tell me if there is an Interceptor point BEFORE the routes are rendered? Or am I barking up the wrong tree here?

Many thanks in advance!

Jason

How is the page stored in the database?

I am assuming that the entire content is stored in the database?

As you don’t provide the error message being shown then try something like this

public void function preEvent(required event, required interceptData){

rc = event.getCollection();

var slug = cgi.path_info;

var page = getPageBySlug(slug);

if (!isNull(page)){

event.setView(‘cms/page’;

rc.cmscontent = page;

} else {

renderdata();

}

}

Now with the renderdata, you need to make that display the content and format that you wish.

Hi Andrew, thanks for your reply.

The problem isn’t with the preEvent Interceptor. This is working perfectly.

The problem is with the routes.

If I don’t have a route defined, it all works perfectly, but when I define the following route:

addRoute(pattern=":handler/:action");
I get the following error if the slug matches that route:

`
The event: test-page.sub-nav-one is not valid registered event.

`

So it looks like the Routes are attempting to process the URL before the process has reached my interceptor.

So what I want to do is run the interceptor BEFORE Coldbox has attempted to resolve the URL to an event as per the set Route.

I could just not have any Routes defined and the interceptor will run fine, but I want to be able to pass in /:handle/:action/ routes that are processed as normal if a page is not found that matches the url.

So the process I am wanting is:

  1. Using the interceptor, check if there is a page in the DB with a slug that matches the cgi.path_info. If yes, process and render that page.

  2. If no, just continue on with the normal CB application flow (processing as per route definitions).

So in short, all I am really needing to do is run the interceptor BEFORE routes are process, and not after.

Thanks again.

Jason

Yes, I understand the problem. However I am not sure I understand exactly what you are trying to do?

Here is what I am hearing. If you browse

/page/something-in-the-water

It runs your handler, if the page slug is in the DB then that is rendered, if not it renders the normal view. If that is the case have a look at my solution again.

If it is not what you are doing, I think you may need to explain it a little differently. Taking out the error, may help me understand what your logic flow is wanting to be.

Hi Jason,

I would suggest read about ColdBox AroundHandler.
http://wiki.coldbox.org/wiki/EventHandlers.cfm#Around_Advice_Intercpetors

Jason,

The interception points are here: http://wiki.coldbox.org/wiki/RequestLifecycles.cfm and here http://wiki.coldbox.org/wiki/Interceptors.cfm

The one you are looking for is onRequestCapture(). This occurs before any preProcess() and SES matching. Just make sure your itnerceptor is defined before the SES interceptor.

+1 on what Luis said. onRequestCapture will allow you to parse the URl first before ColdBox gets to it.

Something else to consider though-- if you are willing to have all your content slugs fall after a placeholder bit of text you can accomplish what you want with an additional route placed before the default one. In these examples, the word “page” is a special place holder for your route to match against (and assumes you never have a handler or package called “page”:

example.com/page/slug1
example.com/page/slug2
example.com/page/slug3
example.com/page/slug4

Then do routes something like this:

addRoute(pattern=“page/:slug” handler=“SlugHandler” action=“doSlug”);
addRoute(pattern=":handler/:action");

Then all requests that start with “page” will be passed to SlugHandler.doSlug for processing with the actual slug value placed in the rc and named “slug” and you can process away. All other requests won’t match the first route, so they will fall through to the second route for processing.

The way ContentBox gets away without having a string like “page” in the URL is it takes over and processes ALL requests through the CMS.

// Catch All Page Routing
{pattern="/:pageSlug", handler=“page”, action=“index”},

If you wanted, you could do this (as you’ve tried) and then in your code, if the slug doesn’t exist, manually parse the URL and do runEvent on the actual event. Honestly, I’d probably do it the other way around though. Just leave the default route, and then in an onInvalidEvent handler or onInvalidEvent interceptor fall back to the slug behavior if the URL doesn’t match a handler.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Thanks everyone for all the great advice and options!

onRequestCapture() is the interceptor I was looking for. Thanks Luis! Only problem I ran into though is that even though this intercepted at the point I needed, the process still continued onto the routes and returned event not found error. I tried to address this with runEvent() in my interceptor, or changing the URI with pathInfoProvider() in Routes.cfm, but didn’t have much luck.

In the end, I settled on Brads suggestion of letting the routes process first, then handling the slug in onInvalidEvent(). This worked a treat and has given me exactly the outcome I was aiming for.

Thanks again all, and Thanks to Luis and Brad for such an amazing framework!

Jason

That is why I was asking more on what you are trying to achieve. Personally I would have gone with Brad’s first suggestion, combined with mine. The reason I wanted to ask what you want, because it wasn’t clear as it screamed a better process.

I think Brad’s first one is better, because too much reliance on the onMissingMethod can lead to poor performance, even if it is only slight overheads, they add up. But to create a page handler to a common input, like Brad showed in his first example.

You can then use that to decide if the page is in the database to render that, then either throw a page not found or process back to the front page or something. By putting the code back into the handler, you are in essence not running this on every process or event, even though you can lock it down to an event. But that interceptor is still cycling code even just doing the event checking, where as with a handler it only gets run when it is actually called.

Same with onMissingMethod, this gets called every time a missing method occurs, then checked for what you are looking for then continues, again taking up extra processing without the need for it.