Routing
Overview
Routing is the term used to describe how a URL gets mapped to actions and input variables in your application. In Preside, the action will be a Coldbox event handler and the input variables will appear in your request context.
We use Coldbox's own routing system along with a Preside addition for handling dynamic routes. When creating your own custom routes, you are free to use either system.
URLs can be built with event.buildLink()
. Different routing URLs will be generated depending on the arguments passed to the buildLink()
function.
Creating custom routes
To create custom routes for your site, you must create a Routes.cfm
file in your /application/config/
directory. In this file, you can create regular ColdBox routes as well as Preside routes. The following routes.cfm
file registers a couple of Preside route handlers:
addRouteHandler( getModel( "myCustomRouteHandler" ) );
addRouteHandler( CreateObject( "app.routeHandlers.anotherCustomRouteHandler" ).init() );
Preside Route Handlers
A Preside Route Handler is any CFC that implements a simple interface to handle routing. The interface looks like this:
interface {
// match(): return true if the incoming URL path should be handled by this route handler
public boolean function match( required string path, required any event ) {}
// translate(): take an incoming URL and translate it - use the ColdBox event object to set variables and the current event
public void function translate( required string path, required any event ) {}
// reverseMatch(): return true if the incomeing set of arguments passed to buildLink() should be handled by this route handler
public boolean function reverseMatch( required struct buildArgs ) {}
// build(): take incoming buildLink() arguments and return a URL string
public string function build( required struct buildArgs ) {}
}
An example route handler, that deals with custom URLs for a "My Profile" area of a website, might look like this:
component implements="preside.system.routeHandlers.iRouteHandler" {
public boolean function match( required string path, required any event ) {
return ReFindNoCase( "^/my-profile/", arguments.path );
}
public void function translate( required string path, required any event ) {
var coldboxEventName = ReReplace( arguments.path, "^/my-profile/", "myprofilemodule:myprofile/" );
coldboxEventName = ListChangeDelims( coldboxEventName, ".", "/" );
if ( ListLen( coldboxEventName, "." ) lt 2 ) {
coldboxEventName = coldboxEventName & "." & "index";
}
event.setValue( "event", coldboxEventName );
}
public boolean function reverseMatch( required struct buildArgs ) {
return Len( Trim( buildArgs.linkTo ?: "" ) ) and ListFirst( buildArgs.linkTo, "." ) eq "myprofilemodule:myprofile";
}
public string function build( required struct buildArgs ) {
var link = "/my-profile/#ListChangeDelims( ListRest( buildArgs.linkTo, "." ), "/", "." )#/";
if ( Len( Trim( buildArgs.queryString ?: "" ) ) ) {
link &= "?" & buildArgs.queryString;
}
return link;
}
}
URL Rewriting
In order for the core routes to work, URL rewrites need to be in place. Preside server distributions ship with the Tuckey URL rewrite filter installed and expect to find a urlrewrite.xml
file in your webroot. The Preside site skeleton builder creates one of these for you with the following rules which you are then free to modify and/or augment:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN" "http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
<urlrewrite>
<rule>
<note>
All request to system static assets that live under /preside/system/assets
should go through Railo and will be rewritten to /index.cfm
</note>
<from>^/preside/system/assets/.*$</from>
<to>%{context-path}/index.cfm</to>
</rule>
<rule>
<note>
All request to *.html or ending in / will be rewritten to /index.cfm
</note>
<from>^(/((.*?)(\.html|/))?)$</from>
<to>%{context-path}/index.cfm</to>
</rule>
<rule>
<note>
Disable Lucee Context except for local requests
</note>
<condition type="remote-addr" operator="notequal">^(127\.0\.0\.1|0:0:0:0:0:0:0:1)$</condition>
<from>^/lucee/.*$</from>
<set type="status">404</set>
<to>null</to>
</rule>
<rule>
<note>
All the following requests should not be allowed and should return with a 404
We block any request to:
* the application folder (where all the logic and views for your site lives)
* the uploads folder (should be configured to be somewhere else anyways)
* this url rewrite file!
</note>
<from>^/(application/|uploads/|urlrewrite\.xml\b)</from>
<set type="status">404</set>
<to>null</to>
</rule>
</urlrewrite>
Out-of-the-box routes
Site tree pages
Any URL that ends with .html
followed by an optional query string, will be routed as a site tree page URL. The "directories" and "filename" will correspond to the slugs of the pages in your tree. For example:
/about-us/meet-the-team/alex-skinner.html?showComments=true
will be routed to:
Coldbox event : core.SiteTreePageRequestHandler
Coldbox RC : { showComments : true }
Coldbox PRC : { slug : "about-us.meet-the-team.alex-skinner" }
and map to the site tree page:
/about-us
/meet-the-team
alex-skinner
Tip
You can build a link to a site tree page with event.buildLink( page=idOfThePage )
Preside Admin pages and actions
Any URL that begins with /(adminPath)
and ends in a forward slash followed by an optional query string, will be routed as a Preside admin request. Directory nodes in the URL will be translated to the ColdBox event.
Info
Your admin path can be configured in your site's Config.cfc
file with the settings.preside_admin_path
setting. The setting defaults to "preside_admin".
For example, assuming that settings.preside_admin_path
has been set to "acme_cmsarea", the URL /acme_cmsarea/sitetree/editPage/?id=F4554E4C-9347-4F7E-B5F862595BFC9EBF
will be routed to:
Coldbox event : admin.sitetree.editPage
Coldbox RC : { id : "F4554E4C-9347-4F7E-B5F862595BFC9EBF" }
Tip
You can build a link to an admin event with event.buildAdminLink( linkTo="sitetree.editPage", queryString="id=#pageId#" )
or event.buildLink( linkTo="admin.sitetree.editPage", queryString="id=#pageId#" )
Asset manager assets
Assets stored in the asset manager are served through the application. Any URL that starts with /asset
and ends with a trailing slash will be routed to the asset manager download action. URLs take the form: /asset/(asset ID)/
or /asset/(asset ID)/(ID or name of derivative)/
. So the URL, /asset/F4554E4C-9347-4F7E-B5F862595BFC9EBF/
, is routed to:
Coldbox event : core.assetDownload
Coldbox RC : { assetId : "F4554E4C-9347-4F7E-B5F862595BFC9EBF" }
and /asset/F4554E4C-9347-4F7E-B5F862595BFC9EBF/headerImage/
becomes:
Coldbox event : core.assetDownload
Coldbox RC : { assetId : "F4554E4C-9347-4F7E-B5F862595BFC9EBF", derivativeId : "headerImage" }
Tip
You can build a link to an asset with event.buildAdminLink( assetId=myAssetId )
or event.buildLink( assetId=myAssetId, derivative=derivativeId )