Security Advisories (2)
CVE-2024-58134 (2025-05-03)

Mojolicious versions from 0.999922 for Perl uses a hard coded string, or the application's class name, as a HMAC session secret by default. These predictable default secrets can be exploited to forge session cookies. An attacker who knows or guesses the secret could compute valid HMAC signatures for the session cookie, allowing them to tamper with or hijack another user's session.

CVE-2024-58135 (2025-05-03)

Mojolicious versions from 7.28 for Perl may generate weak HMAC session secrets. When creating a default app with the "mojo generate app" tool, a weak secret is written to the application's configuration file using the insecure rand() function, and used for authenticating and protecting the integrity of the application's sessions. This may allow an attacker to brute force the application's session keys.

NAME

Mojolicious::Routes::Route - Route

SYNOPSIS

use Mojolicious::Routes::Route;

my $r = Mojolicious::Routes::Route->new;

DESCRIPTION

Mojolicious::Routes::Route is the route container used by Mojolicious::Routes.

ATTRIBUTES

Mojolicious::Routes::Route implements the following attributes.

children

my $children = $r->children;
$r           = $r->children([Mojolicious::Routes::Route->new]);

The children of this route, used for nesting routes.

inline

my $bool = $r->inline;
$r       = $r->inline($bool);

Allow "under" semantics for this route.

parent

my $parent = $r->parent;
$r         = $r->parent(Mojolicious::Routes::Route->new);

The parent of this route, usually a Mojolicious::Routes::Route object. Note that this attribute is weakened.

partial

my $bool = $r->partial;
$r       = $r->partial($bool);

Route has no specific end, remaining characters will be captured in path.

pattern

my $pattern = $r->pattern;
$r          = $r->pattern(Mojolicious::Routes::Pattern->new);

Pattern for this route, defaults to a Mojolicious::Routes::Pattern object.

METHODS

Mojolicious::Routes::Route inherits all methods from Mojo::Base and implements the following new ones.

add_child

$r = $r->add_child(Mojolicious::Routes::Route->new);

Add a child to this route, it will be automatically removed from its current parent if necessary.

# Reattach route
$r->add_child($r->find('foo'));

any

my $route = $r->any;
my $route = $r->any('/:foo');
my $route = $r->any('/:foo' => sub ($c) {...});
my $route = $r->any('/:foo' => sub ($c) {...} => 'name');
my $route = $r->any('/:foo' => {foo => 'bar'} => sub ($c) {...});
my $route = $r->any('/:foo' => [foo => qr/\w+/] => sub ($c) {...});
my $route = $r->any('/:foo' => (agent => qr/Firefox/) => sub ($c) {...});
my $route = $r->any(['GET', 'POST'] => '/:foo' => sub ($c) {...});
my $route = $r->any(['GET', 'POST'] => '/:foo' => [foo => qr/\w+/]);

Generate Mojolicious::Routes::Route object matching any of the listed HTTP request methods or all.

# Route with pattern and destination
$r->any('/user')->to('user#whatever');

All arguments are optional, but some have to appear in a certain order, like the two supported array reference values, which contain the HTTP methods to match and restrictive placeholders.

# Route with HTTP methods, pattern, restrictive placeholders and destination
$r->any(['DELETE', 'PUT'] => '/:foo' => [foo => qr/\w+/])->to('foo#bar');

There are also two supported string values, containing the route pattern and the route name, defaulting to the pattern / and a name based on the pattern.

# Route with pattern, name and destination
$r->any('/:foo' => 'foo_route')->to('foo#bar');

An arbitrary number of key/value pairs in between the route pattern and name can be used to specify route conditions.

# Route with pattern, condition and destination
$r->any('/' => (agent => qr/Firefox/))->to('foo#bar');

A hash reference is used to specify optional placeholders and default values for the stash.

# Route with pattern, optional placeholder and destination
$r->any('/:foo' => {foo => 'bar'})->to('foo#bar');

And a code reference can be used to specify a cb value to be merged into the default values for the stash.

# Route with pattern and a closure as destination
$r->any('/:foo' => sub ($c) {
  $c->render(text => 'Hello World!');
});

See Mojolicious::Guides::Tutorial and Mojolicious::Guides::Routing for more information.

delete

my $route = $r->delete;
my $route = $r->delete('/:foo');
my $route = $r->delete('/:foo' => sub ($c) {...});
my $route = $r->delete('/:foo' => sub ($c) {...} => 'name');
my $route = $r->delete('/:foo' => {foo => 'bar'} => sub ($c) {...});
my $route = $r->delete('/:foo' => [foo => qr/\w+/] => sub ($c) {...});
my $route = $r->delete('/:foo' => (agent => qr/Firefox/) => sub ($c) {...});

Generate Mojolicious::Routes::Route object matching only DELETE requests, takes the same arguments as "any" (except for the HTTP methods to match, which are implied). See Mojolicious::Guides::Tutorial and Mojolicious::Guides::Routing for more information.

# Route with destination
$r->delete('/user')->to('user#remove');

find

my $route = $r->find('foo');

Find child route by name, custom names have precedence over automatically generated ones.

# Change default parameters of a named route
$r->find('show_user')->to(foo => 'bar');

get

my $route = $r->get;
my $route = $r->get('/:foo');
my $route = $r->get('/:foo' => sub ($c) {...});
my $route = $r->get('/:foo' => sub ($c) {...} => 'name');
my $route = $r->get('/:foo' => {foo => 'bar'} => sub ($c) {...});
my $route = $r->get('/:foo' => [foo => qr/\w+/] => sub ($c) {...});
my $route = $r->get('/:foo' => (agent => qr/Firefox/) => sub ($c) {...});

Generate Mojolicious::Routes::Route object matching only GET requests, takes the same arguments as "any" (except for the HTTP methods to match, which are implied). See Mojolicious::Guides::Tutorial and Mojolicious::Guides::Routing for more information.

# Route with destination
$r->get('/user')->to('user#show');

has_custom_name

my $bool = $r->has_custom_name;

Check if this route has a custom name.

has_websocket

my $bool = $r->has_websocket;

Check if this route has a WebSocket ancestor and cache the result for future checks.

is_endpoint

my $bool = $r->is_endpoint;

Check if this route qualifies as an endpoint.

is_reserved

my $bool = $r->is_reserved('controller');

Check if string is a reserved stash value.

is_websocket

my $bool = $r->is_websocket;

Check if this route is a WebSocket.

methods

my $methods = $r->methods;
$r          = $r->methods('GET');
$r          = $r->methods('GET', 'POST');
$r          = $r->methods(['GET', 'POST']);

Restrict HTTP methods this route is allowed to handle, defaults to no restrictions.

# Route with two methods and destination
$r->any('/foo')->methods('GET', 'POST')->to('foo#bar');

name

my $name = $r->name;
$r       = $r->name('foo');

The name of this route, defaults to an automatically generated name based on the route pattern. Note that the name current is reserved for referring to the current route.

# Route with destination and custom name
$r->get('/user')->to('user#show')->name('show_user');

options

my $route = $r->options;
my $route = $r->options('/:foo');
my $route = $r->options('/:foo' => sub ($c) {...});
my $route = $r->options('/:foo' => sub ($c) {...} => 'name');
my $route = $r->options('/:foo' => {foo => 'bar'} => sub ($c) {...});
my $route = $r->options('/:foo' => [foo => qr/\w+/] => sub ($c) {...});
my $route = $r->options('/:foo' => (agent => qr/Firefox/) => sub ($c) {...});

Generate Mojolicious::Routes::Route object matching only OPTIONS requests, takes the same arguments as "any" (except for the HTTP methods to match, which are implied). See Mojolicious::Guides::Tutorial and Mojolicious::Guides::Routing for more information.

# Route with destination
$r->options('/user')->to('user#overview');

parse

$r = $r->parse('/user/:id');
$r = $r->parse('/user/:id', id => qr/\d+/);
$r = $r->parse(format => ['json', 'yaml']);

Parse pattern.

patch

my $route = $r->patch;
my $route = $r->patch('/:foo');
my $route = $r->patch('/:foo' => sub ($c) {...});
my $route = $r->patch('/:foo' => sub ($c) {...} => 'name');
my $route = $r->patch('/:foo' => {foo => 'bar'} => sub ($c) {...});
my $route = $r->patch('/:foo' => [foo => qr/\w+/] => sub ($c) {...});
my $route = $r->patch('/:foo' => (agent => qr/Firefox/) => sub ($c) {...});

Generate Mojolicious::Routes::Route object matching only PATCH requests, takes the same arguments as "any" (except for the HTTP methods to match, which are implied). See Mojolicious::Guides::Tutorial and Mojolicious::Guides::Routing for more information.

# Route with destination
$r->patch('/user')->to('user#update');

post

my $route = $r->post;
my $route = $r->post('/:foo');
my $route = $r->post('/:foo' => sub ($c) {...});
my $route = $r->post('/:foo' => sub ($c) {...} => 'name');
my $route = $r->post('/:foo' => {foo => 'bar'} => sub ($c) {...});
my $route = $r->post('/:foo' => [foo => qr/\w+/] => sub ($c) {...});
my $route = $r->post('/:foo' => (agent => qr/Firefox/) => sub ($c) {...});

Generate Mojolicious::Routes::Route object matching only POST requests, takes the same arguments as "any" (except for the HTTP methods to match, which are implied). See Mojolicious::Guides::Tutorial and Mojolicious::Guides::Routing for more information.

# Route with destination
$r->post('/user')->to('user#create');

put

my $route = $r->put;
my $route = $r->put('/:foo');
my $route = $r->put('/:foo' => sub ($c) {...});
my $route = $r->put('/:foo' => sub ($c) {...} => 'name');
my $route = $r->put('/:foo' => {foo => 'bar'} => sub ($c) {...});
my $route = $r->put('/:foo' => [foo => qr/\w+/] => sub ($c) {...});
my $route = $r->put('/:foo' => (agent => qr/Firefox/) => sub ($c) {...});

Generate Mojolicious::Routes::Route object matching only PUT requests, takes the same arguments as "any" (except for the HTTP methods to match, which are implied). See Mojolicious::Guides::Tutorial and Mojolicious::Guides::Routing for more information.

# Route with destination
$r->put('/user')->to('user#replace');

remove

$r = $r->remove;

Remove route from parent.

# Remove route completely
$r->find('foo')->remove;

# Reattach route to new parent
$r->any('/foo')->add_child($r->find('bar')->remove);

render

my $path = $r->render({foo => 'bar'});

Render route with parameters into a path.

root

my $root = $r->root;

The Mojolicious::Routes object this route is a descendant of.

requires

my $requires = $r->requires;
$r           = $r->requires(foo => 1);
$r           = $r->requires(foo => 1, bar => {baz => 'yada'});
$r           = $r->requires([foo => 1, bar => {baz => 'yada'}]);

Activate conditions for this route. Note that this automatically disables the routing cache, since conditions are too complex for caching.

# Route with condition and destination
$r->get('/foo')->requires(host => qr/mojolicious\.org/)->to('foo#bar');

suggested_method

my $method = $r->suggested_method;

Suggested HTTP method for reaching this route, GET and POST are preferred.

to

my $defaults = $r->to;
$r           = $r->to(action => 'foo');
$r           = $r->to({action => 'foo'});
$r           = $r->to('controller#action');
$r           = $r->to('controller#action', foo => 'bar');
$r           = $r->to('controller#action', {foo => 'bar'});
$r           = $r->to(Mojolicious->new);
$r           = $r->to(Mojolicious->new, foo => 'bar');
$r           = $r->to(Mojolicious->new, {foo => 'bar'});
$r           = $r->to('MyApp');
$r           = $r->to('MyApp', foo => 'bar');
$r           = $r->to('MyApp', {foo => 'bar'});

Set default parameters for this route.

to_string

my $str = $r->to_string;

Stringify the whole route.

under

my $route = $r->under(sub ($c) {...});
my $route = $r->under('/:foo' => sub ($c) {...});
my $route = $r->under('/:foo' => {foo => 'bar'});
my $route = $r->under('/:foo' => [foo => qr/\w+/]);
my $route = $r->under('/:foo' => (agent => qr/Firefox/));
my $route = $r->under([format => ['json', 'yaml']]);

Generate Mojolicious::Routes::Route object for a nested route with its own intermediate destination, takes the same arguments as "any" (except for the HTTP methods to match, which are not available). See Mojolicious::Guides::Tutorial and Mojolicious::Guides::Routing for more information.

# Longer version
$r->any('/:foo' => sub ($c) {...})->inline(1);

# Intermediate destination and prefix shared between two routes
my $auth = $r->under('/user')->to('user#auth');
$auth->get('/show')->to('#show');
$auth->post('/create')->to('#create');

websocket

my $route = $r->websocket;
my $route = $r->websocket('/:foo');
my $route = $r->websocket('/:foo' => sub ($c) {...});
my $route = $r->websocket('/:foo' => sub ($c) {...} => 'name');
my $route = $r->websocket('/:foo' => {foo => 'bar'} => sub ($c) {...});
my $route = $r->websocket('/:foo' => [foo => qr/\w+/] => sub ($c) {...});
my $route = $r->websocket('/:foo' => (agent => qr/Firefox/) => sub ($c) {...});

Generate Mojolicious::Routes::Route object matching only WebSocket handshakes, takes the same arguments as "any" (except for the HTTP methods to match, which are implied). See Mojolicious::Guides::Tutorial and Mojolicious::Guides::Routing for more information.

# Route with destination
$r->websocket('/echo')->to('example#echo');

SHORTCUTS

In addition to the "ATTRIBUTES" and "METHODS" above you can also call shortcuts provided by "root" on Mojolicious::Routes::Route objects.

# Add a "firefox" shortcut
$r->root->add_shortcut(firefox => sub ($r, $path) {
  $r->get($path, agent => qr/Firefox/);
});

# Use "firefox" shortcut to generate routes
$r->firefox('/welcome')->to('firefox#welcome');
$r->firefox('/bye')->to('firefox#bye');

SEE ALSO

Mojolicious, Mojolicious::Guides, https://mojolicious.org.