[Coldbox-4.0] RESTful route not recognized

I have defined a route matching api/User/:userID that I want to call the api.User handler. I’ve defined my Routes.cfm as follows:

`

// Allow unique URL or combination of URLs, we recommend both enabled setUniqueURLS(false); // Auto reload configuration, true in dev makes sense to reload the routes on every request setAutoReload(false); // Sets automatic route extension detection and places the extension in the rc.format variable setExtensionDetection(true); // The valid extensions this interceptor will detect // setValidExtensions('xml,json,jsont,rss,html,htm'); // If enabled, the interceptor will throw a 406 exception that an invalid format was detected or just ignore it // setThrowOnInvalidExtension(true);

// Base URL
if( len(getSetting(‘AppMapping’) ) lte 1){
setBaseURL(“http://#cgi.HTTP_HOST#”);
}
else{
setBaseURL(“http://#cgi.HTTP_HOST#/#getSetting(‘AppMapping’)#/index.cfm”);
}

// RESRful routes
addRoute(
pattern = “api/User/:userID”,
handler = “api.User”,
action = {
GET = “view”,
POST = “save”,
PUT = “save”,
DELETE = “remove”
}
);

// default route
addRoute(pattern=":handler/:action?");

`

My handler is nothing more than:

`

component extends=“coldbox.system.EventHandler”{
this.allowedMethods = {view = “GET”, save = “POST,PUT”, remove = “DELETE”};

any function view (event, rc, prc) {
//writedump(“view”); abort;
}

any function save (event, rc, prc) {
writedump([rc,prc]); abort;
}

any function remove (event, rc, prc) {
//writedump(“remove”); abort;
}
}

`

When POSTing, my 404 handler is picking up the request. Upon dumping the prc, it appears that my specified route is not being picked up and I believe it’s using the default route.

currentRoute -> :handler/
currentRoutedURL -> api/User/
invalidevent -> api.User.index

Any thoughts on why the pattern doesn’t appear to be matching?

Probably you should set up the route this way:

`

addRoute(
pattern = “api/User/:userID?”,
handler = “api.User”,
action = {
GET = “view”,
POST = “save”,
PUT = “save”,
DELETE = “remove”
}
);

`

Please note the ? at the end of the route.

From your code seems that the route are finding an index event in your handler. If you don’t pass a userId to your route the routed url is “api/User/” that by default should fire an index event in your hanler. But the index is missing.

Can you point me to the documentation explaining the use of ? at the end? I see no mention of it here: http://wiki.coldbox.org/wiki/Building_Rest_APIs.cfm I would assume that the interceptor would be intelligent enough to ignore the :userID slug when POSTing.

http://wiki.coldbox.org/wiki/URLMappings.cfm#Optional_Placeholders

You’re making assumptions about how you’re using routes which wouldn’t be safe for the SES interceptor to make. The routes are used as defined. Any piece of the route you define is assumed to be required unless you mark it as optional regardless of how you plan on using it or what HTTP verbs will be used to access it.

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, Brad. I agree with you on the assumption being bad, however the RESTful examples (noted below) seem to imply that it is assumed the param is optional. POST is typically not idempotent and you wouldn’t create a new user with an ID you don’t know yet. I think it’d be helpful if these RESTful examples were updated to reflect that.

http://wiki.coldbox.org/wiki/Building_Rest_APIs.cfm#Defining_URL_Routes

// Map route to specific user.  Different verbs call different actions!
addRoute(
  pattern = 'api/user/:userID',
  handler = 'api.user',
  action = {
    GET = 'view',
    POST = 'save',
    PUT = 'save',
    DELETE = 'remove'
  });

http://wiki.coldbox.org/wiki/URLMappings.cfm#RESTful_Action_Routing

addRoute(pattern="/user/:username", handler="users", action={
  GET = "list", POST = "create", PUT = "save", DELETE = "remove", HEAD ="info"
});

With that being said, the ? did fix my issue so thank you both for pointing that out!

Thanks,
Tristan Lee

It’s not unheard of for a create operation to supply an ID. Especially if using GUIDs between multiple systems where you don’t just have a single database with an auto-incrementing int.

I can update those examples though if it will help you sleep better at night :slight_smile:

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

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

Agreed, there’s certainly cases where an ID would be supplied so absolutely the code should not assume POSTs don’t take params. I’m not worried so much about sleep as I am just understanding proper implementation. Surely I am not the first to learn REST also running into this confusion, but I can’t say I’d be surprised if I wasn’t :wink: