CatalystX::Routes - Sugar for declaring RESTful chained actions in Catalyst


version 0.02


  package MyApp::Controller::User;

  use Moose;
  use CatalystX::Routes;

  BEGIN { extends 'Catalyst::Controller'; }

  # /user/:user_id

  chain_point '_set_user'
      => chained '/'
      => path_part 'user'
      => capture_args 1
      => sub {
          my $self = shift;
          my $c    = shift;
          my $user_id = shift;

          $c->stash()->{user} = ...;

  # GET /user/:user_Id
  get ''
     => chained('_set_user')
     => args 0
     => sub { ... };

  # GET /user/foo
  get 'foo' => sub { ... };

  sub _post { ... }

  # POST /user/foo
  post 'foo' => \&_post;

  # PUT /root
  put '/root' => sub { ... };

  # /user/plain_old_catalyst
  sub plain_old_catalyst : Local { ... }


WARNING: This module is still experimental. It works well, but the APIs may change without warning.

This module provides a sugar layer that allows controllers to declare chained RESTful actions.

Under the hood, all the sugar declarations are turned into Chained subs. All chain end points are declared using one of get, get_html, post, put, or del. These will declare actions using the Catalyst::Action::REST::ForBrowsers action class from the Catalyst::Action::REST distribution.


This module is merely sugar over Catalyst's built-in Chained dispatching and Catalyst::Action::REST. It helps to know how those two things work.


All of these functions will be exported into your controller class when you use CatalystX::Routes.

get ...

This declares a GET handler.


This declares a GET handler for browsers. Use this to generate a standard HTML page for browsers while still being able to generate some sort of RESTful data response for other clients.

If a browser makes a GET request and no get_html action has been declared, a get action is used as a fallback. See Catalyst::TraitFor::Request::REST::ForBrowsers for details on how "browser-ness" is determined.

post ...

This declares a POST handler.


This declares a PUT handler.


This declares a DELETE handler.


This declares an intermediate chain point that should not be exposed as a public URI.

chained $path

This function takes a single argument, the previous chain point from which the action is chained.

args $number

This declares the number of arguments that this action expects. This should only be used for the end of a chain.

capture_args $number

The number of arguments to capture at this point in the chain. This should only be used for the beginning or middle parts of a chain.

path_part $path

The path part for this part of the chain. If you are declaring a chain end point with get, etc., then this isn't necessary. By default, the name passed to the initial sugar function will be converted to a path part. See below for details.

action_class_name $class

Use this to declare an action class. By default, this will be Catalyst::Action::REST::ForBrowsers for end points. For other parts of a chain, it simply won't be set.


All of the end point function (get, post, etc.) take a path as the first argument. By default, this will be used as the path_part for the chain. You can override this by explicitly calling path_part, in which case the name is essentially ignored (but still required).

Note that it is legitimate to pass the empty string as the name for a chain's end point.

If the end point's name does not start with a slash, it will be prefixed with the controller's namespace.

If you don't specify a chained value for an end point, then it will use the root URI, /, as the root of the chain.

By default, no arguments are specified for a chain's end point, meaning it will accept any number of arguments.


When adding subroutines for end points to your controller, a name is generated for each subroutine based on the chained path to the subroutine. Some template-based views will automatically pick a template based on the subroutine's name if you don't specify one explicitly. This won't work very well with the bizarro names that this module generates, so you are strongly encouraged to specify a template name explicitly.


Please report any bugs or feature requests to, or through the web interface at I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


Dave Rolsky <>


This software is Copyright (c) 2011 by Dave Rolsky.

This is free software, licensed under:

  The Artistic License 2.0