Skip to content


Folders and files

Last commit message
Last commit date

Latest commit


Repository files navigation


use Router::Right;

my $r = Router::Right->new;

$r->add(home => '/', 'Home#show');
$r->add(blog => '/blog/{year}/{month}', 'Blog#monthly');

my $match = $r->match('/blog/1916/08'); 

# Returns {
#   controller => 'Blog',
#   action => 'monthly',
#   year => '1916',
#   month => '08',
# }


Router::Right is a Perl5-based, framework-agnostic routing engine used to map web application request URLs to application handlers.


  • new()

    Returns a new Router::Right instance

  • add($name => $route_path, \%payload [, %options])

    Define a route. $name is used to reference the route elsewhere. On a successful match, the payload hash reference is returned; by convention, a payload includes "controller" and "action" values. For example:

      $r->add(entries => '/entries', { controller => 'Entries', action => 'show' })

    See the ROUTE DEFINITION section for details on how $route_path values are specified.

    Also, if the payload consists solely of controller and action values, it can be specified as a string in the format "controller#action". For example:

      $r->add(entries => '/entries', 'Entries#show')

    is exactly equivalent to specifying a payload of: { controller => 'Entries', action => 'show' }.

    By default, routes match any HTTP request method (e.g., GET, POST). To restrict them, supply a "methods" option. e.g.,

      $r->add(entries => '/entries', 'Entries#show', methods => 'GET')

    That would only match GET requests. The value may be either a string or an array reference of strings. e.g.,

      $r->add(entries => '/entries', 'Entries#show', methods => [qw/ GET POST /])

    Method strings are case-insensitive. As a convenience, the allowed methods can also be specified as part of the route path itself. e.g.,

      $r->add(entries => 'GET|POST /entries', 'Entries#show')
  • match($url [, $method])

    Attempts to find a route that matches the supplied $url. Routes are matched in the order defined.

    If a match is found, its associated payload is returned. If not, undef is returned and the error() method will indicate why the match failed.

    $method, if supplied, is the HTTP method of the request (e.g., GET, POST, etc.). Specifying $method may prevent a route from otherwise matching if the route was defined with a restricted set of allowed methods (see ROUTE DEFINITION). By default, all request methods are allowed.

    While the payload is always a hash reference, starting with version 1.05, it is also blessed into the Router::Right::Match class, which provides access to the route definition that resulted in the match.

  • error()

    Returns the error code of the last failed match.

      404 = no match found
      405 = method not allowed

    A 405 result indicates a match was found, but the request method was not allowed. allowed_methods() can be called to obtain a list of the methods that are permitted for the route.

    The above error codes are also available as symbolic constants through the NOT_FOUND and METHOD_NOT_ALLOWED functions.

  • allowed_methods([ $name ])

    Returns the list of allowed methods for a given route name or path. In list context, returns a list. In scalar context, returns an array reference. An empty list/array indicates that all methods are permitted.

    If route $name is supplied, returns its permitted methods. Returns undef in scalar context if the route is unknown. If $name contains a forward slash, it's intepreted as a route path, instead.

    With no argument, returns the methods permitted by the last match() attempt. Returns undef in scalar context if there was no prior match.

      $r->add(entries => 'PUT|GET /entries', { controller => 'Entries' });
      print join(', ', $r->allowed_methods('entries')), "\n"; # prints GET, PUT
  • url($name [, %params])

    Constructs a URL from the $name route. Placeholder values are supplied as %params. Unknown placeholder values are appended as query string parameters.


      $r->add(entry => '/entries/{year}', { controller => 'Entry' });
      $r->url('entry', year => '1916', q => 'abc'); # produces /entries/1916?q=abc 

    The return value is a URI instance.

  • as_string()

    Returns a report of the defined routes, in order of definition.

  • with($name => $route_path [, %options]

    Helper method to share information across multiple routes. For example:

      $r->with(admin => '/admin',        'Admin')
        ->add(users  => '/users',        '#users')
        ->add(trx    => '/transactions', '#transactions')
      print $r->as_string;
      # prints:
      #   admin_users * /admin/users        { action => "users", controller => "Admin" }
      #   admin_trx   * /admin/transactions { action => "transactions", controller => "Admin" }

    The payload contents are merged. The route names are joined by an underscore. The paths are concatenated. Either or both of $name and $route_path may be undefined.

    If a nested route specifies a controller beginning with '::', it is concatenated with the outer controller name. For example:

      $r->with(admin => '/admin', 'Admin')
        ->add(users  => '/users', '::User#show')
      print $r->as_string;
      # prints:
      #   admin_users * /admin/users { action => "show", controller => "Admin::User" }

    A callback is accepted, which allows chaining with() calls:

      $r->with(admin => '/admin',  { controller => 'Admin' }, call => sub {
        $_->add(users => '/users', { action => 'users' });
        $_->add(log   => '/log',   { action => 'log' });
      })->with(dashboard => '/dashboard', { controller => 'Admin::Dashboard' }, call => sub {
        $_->add(view => '/{action}');
      print $r->as_string;
      # prints:
      #   admin_users          * /admin/users
      #   admin_log            * /admin/log
      #   admin_dashboard_view * /admin/dashboard/{action}

    Within the callback function, $_ is set to the router instance. It is also supplied as a parameter.

  • resource($name, \%payload [, %options])

    Adds routes to create, read, update, and delete a given resource. For example:

      my $r = Router::Right->new->resource('message', { controller => 'Message' });
      print $r->as_string, "\n";
      # prints:
      #                 messages GET    /messages{.format}           { action => "index", controller => "Message" }
      #                          POST   /messages{.format}           { action => "create", controller => "Message" }
      #       formatted_messages GET    /messages.{format}           { action => "index", controller => "Message" }
      #              new_message GET    /messages/new{.format}       { action => "new", controller => "Message" }
      #    formatted_new_message GET    /messages/new.{format}       { action => "new", controller => "Message" }
      #                  message GET    /messages/{id}{.format}      { action => "show", controller => "Message" }
      #                          PUT    /messages/{id}{.format}      { action => "update", controller => "Message" }
      #                          DELETE /messages/{id}{.format}      { action => "delete", controller => "Message" }
      #        formatted_message GET    /messages/{id}.{format}      { action => "show", controller => "Message" }
      #             edit_message GET    /messages/{id}{.format}/edit { action => "edit", controller => "Message" }
      #   formatted_edit_message GET    /messages/{id}.{format}/edit { action => "edit", controller => "Message" }


A route path is a normal URL path with the addition of placeholder variables. For example:

$r->add(entries => '/entries/{year}/{month}');

defines a route path containing two placeholders, "year" and "month'. By default, a placeholder matches any string up to the next forward slash.

Placeholder names must not begin with a number, nor contain hyphens or forward slashes.

The default match rule may be overridden. For example:

$r->add(entries => '/entries/{year:\d+}/{month:\d+}');

is the same as above, except it will only match if both the year and month contain only digits.

The special {.format} placeholder can be used to allow an optional file extension to be appended. For example:

$r->add(download => '/dl/{file}{.format}', { controller => 'Download' });
$r->match('/dl/foo.gz'); # returns { controller => 'Download', file => 'foo', format => 'gz' }
$r->match('/dl/foo');    # returns { controller => 'Download', file => 'foo' }

# And to build a URL from it:
$r->url('download', file => 'foo', format => 'bz2'); # /dl/foo.bz2


Router::Right is based on Tokuhiro Matsuno's Router::Simple and Router::Boom modules.

This module seeks to implement most features of Python's Routes:


Perl-based, framework-agnostic URL routing engine for web applications






No packages published