NAME

URI::Dispatch - determine which code to execute based upon path

SYNOPSIS

my $dispatch = URI::Dispatch->new();
$dispatch->add( '/', 'homepage' );

# common matching patterns are available
$dispatch->add( '/user/#id', 'profile' );

# optional parts of the path
$dispatch->add( '/article/#id[/#slug]', 'article' );

# named captures
$dispatch->add( '/tag/#name:slug', 'tag' );

# use a custom regexp
$dispatch->add( '/a-z/#letter:([a-z])', 'az-page' );

# pass in a path and determine what matches
my( $handler, $options) 
    = $dispatch->handler( '/article/5/awesome-article' );
# handler='article', options=['5','awesome-article']

# construct paths
my $uri = $dispatch->url( 'article', [ '1', 'some-article' ] );
# uri='/article/1/some-article'

METHODS

add( path, handler )

Add path that can be handled by handler. The path string is a literal string, with special markers.

captures

To capture part of the path for later use, mark it with a hash (#) and the capture type. Builtin types are:

id

matches digits

hex

matches digits and the letters a, b, c, d, e, and f case insensitively

slug

matches lowercase letters, digits and hyphens

year

matches four digits

month

matches numbers 01 through 12

day

matches numbers 01 through 31

*

matches anything

(regexp)

matches a custom regular expression

named captures

Rather than relying on the order of the captures, they can be named. The name goes immediately after the hash (#), is formed of "word" characters (alphanumeric plus underscore) and is followed by a colon and then the capture type. Some examples:

  • #id:id

  • #title:slug

  • #letter:([a-z])

optional segments

To mark part of the path as optional, surround it with square brackets. Optional segments cannot be nested.

Limitations

Adding a new path with the same handler will overwrite the previous path.

Different handlers having the same path will result in unpredictable behaviour.

handler( path )

Determine which handler should be used for the given path.

Returns the handler string, and either an array of the captured elements, or a hash if the captures were named. For example, this code:

$dispatch->add( '/article/#key:id/#title:slug', 'article' );
my( $handler, $captures )
    = $dispatch->handler( '/article/5/awesome-article' );

will return a data structure equivalent to:

$captures = {
    key   => '5',
    title => 'awesome-article',
};

url( handler, $arguments )

Build a path that handler would accept. If the path contains captures, you can pass them as an arrayref (or hashref if they are named captures).

The $arguments are tested to ensure they would match. If they would not, an Ouch exception is thrown. This can be caught in your code like so:

use Ouch qw( :traditional );

...

$dispatch->add( '/list/#letter:([a-z])', 'az-page' );
try { $url = $dispatch->url( 'az-page', 'too big' ); };
if ( catch 'wrong_input' ) {
    # handle errors
}

EXCEPTIONS

cannot_mix

Named and positional captures cannot be mixed. An attempt to do so will throw this exception.

unmatched_brackets

Thrown if the opening and closing square brackets representing optional segments of a path do not match up.

wrong_input

A provided argument when calling url() will not match the relevant capture type.

args_short

Not enough arguments are provided when calling url().

args_wrong

The wrong type of arguments (arrayref versus hashref) were provided when calling url().

no_param

An unknown builtin parameter type was requested.

AUTHOR

Mark Norman Francis, norm@cackhanded.net.

COPYRIGHT AND LICENSE

Copyright 2011 Mark Norman Francis.

This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0.