Skip to content


Subversion checkout URL

You can clone with
Download ZIP
simple http router
Perl Perl6
branch: master


Router::Simple - simple HTTP router


use Router::Simple;

my $router = Router::Simple->new();
$router->connect('/', {controller => 'Root', action => 'show'});
$router->connect('/blog/{year}/{month}', {controller => 'Blog', action => 'monthly'});

my $app = sub {
    my $env = shift;
    if (my $p = $router->match($env)) {
        # $p = { controller => 'Blog', action => 'monthly', ... }
    } else {
        [404, [], ['not found']];


Router::Simple is a simple router class.

Its main purpose is to serve as a dispatcher for web applications.

Router::Simple can match against PSGI $env directly, which means it's easy to use with PSGI supporting web frameworks.


plain string

$router->connect( '/foo', { controller => 'Root', action => 'foo' } );

:name notation

$router->connect( '/wiki/:page', { controller => 'WikiPage', action => 'show' } );
# => {controller => 'WikiPage', action => 'show', page => 'john' }

':name' notation matches qr{([^/]+)}.

'*' notation

$router->connect( '/download/*.*', { controller => 'Download', action => 'file' } );
# => {controller => 'Download', action => 'file', splat => ['path/to/file', 'xml'] }

'*' notation matches qr{(.+)}. You will get the captured argument as an array ref for the special key splat.

'{year}' notation

$router->connect( '/blog/{year}', { controller => 'Blog', action => 'yearly' } );
# => {controller => 'Blog', action => 'yearly', year => 2010 }

'{year}' notation matches qr{([^/]+)}, and it will be captured.

'{year:[0-9]+}' notation

$router->connect( '/blog/{year:[0-9]+}/{month:[0-9]{2}}', { controller => 'Blog', action => 'monthly' } );
# => {controller => 'Blog', action => 'monthly', year => 2010, month => '04' }

You can specify regular expressions in named captures.


$router->connect( qr{/blog/(\d+)/([0-9]{2})', { controller => 'Blog', action => 'monthly' } );
# => {controller => 'Blog', action => 'monthly', splat => [2010, '04'] }

You can use Perl5's powerful regexp directly, and the captured values are stored in the special key splat.


  • my $router = Router::Simple->new();

    Creates a new instance of Router::Simple.

  • $router->method_not_allowed() : Boolean

    This method returns last $router->match() call is rejected by HTTP method or not.

  • $router->connect([$name, ] $pattern, \%destination[, \%options])

    Adds a new rule to $router.

    $router->connect( '/', { controller => 'Root', action => 'index' } );
    $router->connect( 'show_entry', '/blog/:id',
        { controller => 'Blog', action => 'show' } );
    $router->connect( '/blog/:id', { controller => 'Blog', action => 'show' } );
    $router->connect( '/comment', { controller => 'Comment', action => 'new_comment' }, {method => 'POST'} );

    \%destination will be used by match method.

    You can specify some optional things to \%options. The current version supports 'method', 'host', and 'on_match'.

    • method

      'method' is an ArrayRef[String] or String that matches REQUEST_METHOD in $req.

    • host

      'host' is a String or Regexp that matches HTTP_HOST in $req.

    • on_match

              on_match => sub {
                  my($env, $match) = @_;
                  $match->{referer} = $env->{HTTP_REFERER};
                  return 1;

      A function that evaluates the request. Its signature must be ($environ, $match) => bool. It should return true if the match is successful or false otherwise. The first argument is $env which is either a PSGI environment or a request path, depending on what you pass to match method; the second is the routing variables that would be returned if the match succeeds.

      The function can modify $env (in case it's a reference) and $match in place to affect which variables are returned. This allows a wide range of transformations.

  • $router->submapper($path, [\%dest, [\%opt]])

    $router->submapper('/entry/', {controller => 'Entry'})

    This method is shorthand for creating new instance of Router::Simple::Submapper.

    The arguments will be passed to Router::Simple::SubMapper->new(%args).

  • $match = $router->match($env|$path)

    Matches a URL against one of the contained routes.

    The parameter is either a PSGI $env or a plain string that represents a path.

    This method returns a plain hashref that would look like:

        controller => 'Blog',
        action     => 'daily',
        year => 2010, month => '03', day => '04',

    It returns undef if no valid match is found.

  • my ($match, $route) = $router->routematch($env|$path);

    Match a URL against one of the routes contained.

    Will return undef if no valid match is found, otherwise a result hashref and a Router::Simple::Route object is returned.

  • $router->as_string()

    Dumps $router as string.

    Example output:

    home         GET  /
    blog_monthly GET  /blog/{year}/{month}
                 GET  /blog/{year:\d{1,4}}/{month:\d{2}}/{day:\d\d}
                 POST /comment
                 GET  /


Tokuhiro Matsuno


Tatsuhiko Miyagawa

Shawn M Moore


Router::Simple is inspired by

Path::Dispatcher is similar, but so complex.

Path::Router is heavy. It depends on Moose.

HTTP::Router has many dependencies. It is not well documented.

HTTPx::Dispatcher is my old one. It does not provide an OO-ish interface.




Copyright (C) Tokuhiro Matsuno

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

Something went wrong with that request. Please try again.