1Mojolicious::Guides::RoUusteirngC(o3n)tributed Perl DocuMmoejnotlaitciioonus::Guides::Routing(3)
2
3
4

NAME

6       Mojolicious::Guides::Routing - Routing requests
7

OVERVIEW

9       This document contains a simple and fun introduction to the Mojolicious
10       router and its underlying concepts.
11

CONCEPTS

13       Essentials every Mojolicious developer should know.
14
15   Dispatcher
16       The foundation of every web framework is a tiny black box connecting
17       incoming requests with code generating the appropriate response.
18
19         GET /user/show/1 -> $c->render(text => 'Daniel');
20
21       This black box is usually called a dispatcher. There are many
22       implementations using different strategies to establish these
23       connections, but pretty much all are based around mapping the path part
24       of the request URL to some kind of response generator.
25
26         /user/show/2 -> $c->render(text => 'Isabell');
27         /user/show/3 -> $c->render(text => 'Sara');
28         /user/show/4 -> $c->render(text => 'Stefan');
29         /user/show/5 -> $c->render(text => 'Fynn');
30
31       While it is very well possible to make all these connections static, it
32       is also rather inefficient. That's why regular expressions are commonly
33       used to make the dispatch process more dynamic.
34
35         qr!/user/show/(\d+)! -> $c->render(text => $users{$1});
36
37       Modern dispatchers have pretty much everything HTTP has to offer at
38       their disposal and can use many more variables than just the request
39       path, such as request method and headers like "Host", "User-Agent" and
40       "Accept".
41
42         GET /user/show/23 HTTP/1.1
43         Host: mojolicious.org
44         User-Agent: Mojolicious (Perl)
45         Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
46
47   Routes
48       While regular expressions are quite powerful they also tend to be
49       unpleasant to look at and are generally overkill for ordinary path
50       matching.
51
52         qr!/user/admin/(\d+)! -> $c->render(text => $users{$1});
53
54       This is where routes come into play, they have been designed from the
55       ground up to represent paths with placeholders.
56
57         /user/admin/:id -> $c->render(text => $users{$id});
58
59       The only difference between a static path and the route above is the
60       ":id" placeholder. One or more placeholders can be anywhere in the
61       route.
62
63         /user/:role/:id
64
65       A fundamental concept of the Mojolicious router is that extracted
66       placeholder values are turned into a hash.
67
68         /user/admin/23 -> /user/:role/:id -> {role => 'admin', id => 23}
69
70       This hash is basically the center of every Mojolicious application, you
71       will learn more about this later on.  Internally, routes get compiled
72       to regular expressions, so you can get the best of both worlds with a
73       little bit of experience.
74
75         /user/admin/:id -> qr/(?-xism:^\/user\/admin\/([^\/.]+))/
76
77       A trailing slash in the path is always optional.
78
79         /user/admin/23/ -> /user/:role/:id -> {role => 'admin', id => 23}
80
81   Reversibility
82       One more huge advantage routes have over regular expressions is that
83       they are easily reversible, extracted placeholders can be turned back
84       into a path at any time.
85
86         /sebastian -> /:name -> {name => 'sebastian'}
87         {name => 'sebastian'} -> /:name -> /sebastian
88
89       Every placeholder has a name, even if it's just an empty string.
90
91   Standard placeholders
92       Standard placeholders are the simplest form of placeholders, they use a
93       colon prefix and match all characters except "/" and ".", similar to
94       the regular expression "([^/.]+)".
95
96         /hello              -> /:name/hello -> undef
97         /sebastian/23/hello -> /:name/hello -> undef
98         /sebastian.23/hello -> /:name/hello -> undef
99         /sebastian/hello    -> /:name/hello -> {name => 'sebastian'}
100         /sebastian23/hello  -> /:name/hello -> {name => 'sebastian23'}
101         /sebastian 23/hello -> /:name/hello -> {name => 'sebastian 23'}
102
103       All placeholders can be surrounded by "<" and ">" to separate them from
104       the surrounding text.
105
106         /hello             -> /<:name>hello -> undef
107         /sebastian/23hello -> /<:name>hello -> undef
108         /sebastian.23hello -> /<:name>hello -> undef
109         /sebastianhello    -> /<:name>hello -> {name => 'sebastian'}
110         /sebastian23hello  -> /<:name>hello -> {name => 'sebastian23'}
111         /sebastian 23hello -> /<:name>hello -> {name => 'sebastian 23'}
112
113       The colon prefix is optional for standard placeholders that are
114       surrounded by "<" and ">".
115
116         /i♥mojolicious -> /<one>♥<two> -> {one => 'i', two => 'mojolicious'}
117
118   Relaxed placeholders
119       Relaxed placeholders are just like standard placeholders, but use a
120       hash prefix and match all characters except "/", similar to the regular
121       expression "([^/]+)".
122
123         /hello              -> /#name/hello -> undef
124         /sebastian/23/hello -> /#name/hello -> undef
125         /sebastian.23/hello -> /#name/hello -> {name => 'sebastian.23'}
126         /sebastian/hello    -> /#name/hello -> {name => 'sebastian'}
127         /sebastian23/hello  -> /#name/hello -> {name => 'sebastian23'}
128         /sebastian 23/hello -> /#name/hello -> {name => 'sebastian 23'}
129
130       They can be especially useful for manually matching file names with
131       extensions, rather than using format detection.
132
133         /music/song.mp3 -> /music/#filename -> {filename => 'song.mp3'}
134
135   Wildcard placeholders
136       Wildcard placeholders are just like the two types of placeholders
137       above, but use an asterisk prefix and match absolutely everything,
138       including "/" and ".", similar to the regular expression "(.+)".
139
140         /hello              -> /*name/hello -> undef
141         /sebastian/23/hello -> /*name/hello -> {name => 'sebastian/23'}
142         /sebastian.23/hello -> /*name/hello -> {name => 'sebastian.23'}
143         /sebastian/hello    -> /*name/hello -> {name => 'sebastian'}
144         /sebastian23/hello  -> /*name/hello -> {name => 'sebastian23'}
145         /sebastian 23/hello -> /*name/hello -> {name => 'sebastian 23'}
146
147       They can be useful for manually matching entire file paths.
148
149         /music/rock/song.mp3 -> /music/*filepath -> {filepath => 'rock/song.mp3'}
150

BASICS

152       Most commonly used features every Mojolicious developer should know
153       about.
154
155   Minimal route
156       The attribute "routes" in Mojolicious contains a router you can use to
157       generate route structures.
158
159         # Application
160         package MyApp;
161         use Mojo::Base 'Mojolicious', -signatures;
162
163         sub startup ($self) {
164           # Router
165           my $r = $self->routes;
166
167           # Route
168           $r->get('/welcome')->to(controller => 'foo', action => 'welcome');
169         }
170
171         1;
172
173       The minimal route above will load and instantiate the class
174       "MyApp::Controller::Foo" and call its "welcome" method.  Routes are
175       usually configured in the "startup" method of the application class,
176       but the router can be accessed from everywhere (even at runtime).
177
178         # Controller
179         package MyApp::Controller::Foo;
180         use Mojo::Base 'Mojolicious::Controller', -signatures;
181
182         # Action
183         sub welcome ($self) {
184           # Render response
185           $self->render(text => 'Hello there.');
186         }
187
188         1;
189
190       All routes match in the same order in which they were defined, and
191       matching stops as soon as a suitable route has been found. So you can
192       improve the routing performance by declaring your most frequently
193       accessed routes first. A routing cache will also be used automatically
194       to handle sudden traffic spikes more gracefully.
195
196   Routing destination
197       After you start a new route with methods like "get" in
198       Mojolicious::Routes::Route, you can also give it a destination in the
199       form of a hash using the chained method "to" in
200       Mojolicious::Routes::Route.
201
202         # /welcome -> {controller => 'foo', action => 'welcome'}
203         $r->get('/welcome')->to(controller => 'foo', action => 'welcome');
204
205       Now if the route matches an incoming request it will use the content of
206       this hash to try and find appropriate code to generate a response.
207
208   HTTP methods
209       There are already shortcuts for the most common HTTP request methods
210       like "post" in Mojolicious::Routes::Route, and for more control "any"
211       in Mojolicious::Routes::Route accepts an optional array reference with
212       arbitrary request methods as first argument.
213
214         # PUT /hello  -> undef
215         # GET /hello  -> {controller => 'foo', action => 'hello'}
216         $r->get('/hello')->to(controller => 'foo', action => 'hello');
217
218         # PUT /hello -> {controller => 'foo', action => 'hello'}
219         $r->put('/hello')->to(controller => 'foo', action => 'hello');
220
221         # POST /hello -> {controller => 'foo', action => 'hello'}
222         $r->post('/hello')->to(controller => 'foo', action => 'hello');
223
224         # GET|POST /bye  -> {controller => 'foo', action => 'bye'}
225         $r->any(['GET', 'POST'] => '/bye')->to(controller => 'foo', action => 'bye');
226
227         # * /whatever -> {controller => 'foo', action => 'whatever'}
228         $r->any('/whatever')->to(controller => 'foo', action => 'whatever');
229
230       There is one small exception, "HEAD" requests are considered equal to
231       "GET", but content will not be sent with the response even if it is
232       present.
233
234         # GET /test  -> {controller => 'bar', action => 'test'}
235         # HEAD /test -> {controller => 'bar', action => 'test'}
236         $r->get('/test')->to(controller => 'bar', action => 'test');
237
238       You can also use the "_method" query parameter to override the request
239       method. This can be very useful when submitting forms with browsers
240       that only support "GET" and "POST".
241
242         # PUT  /stuff             -> {controller => 'baz', action => 'stuff'}
243         # POST /stuff?_method=PUT -> {controller => 'baz', action => 'stuff'}
244         $r->put('/stuff')->to(controller => 'baz', action => 'stuff');
245
246   IRIs
247       IRIs are handled transparently, that means paths are guaranteed to be
248       unescaped and decoded from bytes to characters.
249
250         # GET /☃ (Unicode snowman) -> {controller => 'foo', action => 'snowman'}
251         $r->get('/☃')->to(controller => 'foo', action => 'snowman');
252
253   Stash
254       The generated hash of a matching route is actually the center of the
255       whole Mojolicious request cycle. We call it the stash, and it persists
256       until a response has been generated.
257
258         # /bye -> {controller => 'foo', action => 'bye', mymessage => 'Bye'}
259         $r->get('/bye')->to(controller => 'foo', action => 'bye', mymessage => 'Bye');
260
261       There are a few stash values with special meaning, such as "controller"
262       and "action", but you can generally fill it with whatever data you need
263       to generate a response. Once dispatched the whole stash content can be
264       changed at any time.
265
266         sub bye ($self) {
267
268           # Get message from stash
269           my $msg = $self->stash('mymessage');
270
271           # Change message in stash
272           $self->stash(mymessage => 'Welcome');
273         }
274
275       For a full list of reserved stash values see "stash" in
276       Mojolicious::Controller.
277
278   Nested routes
279       It is also possible to build tree structures from routes to remove
280       repetitive code. A route with children can't match on its own though,
281       only the actual endpoints of these nested routes can.
282
283         # /foo     -> undef
284         # /foo/bar -> {controller => 'foo', action => 'bar'}
285         my $foo = $r->any('/foo')->to(controller => 'foo');
286         $foo->get('/bar')->to(action => 'bar');
287
288       The stash is simply inherited from route to route and newer values
289       override old ones.
290
291         # /cats      -> {controller => 'cats', action => 'index'}
292         # /cats/nyan -> {controller => 'cats', action => 'nyan'}
293         # /cats/lol  -> {controller => 'cats', action => 'default'}
294         my $cats = $r->any('/cats')->to(controller => 'cats', action => 'default');
295         $cats->get('/')->to(action => 'index');
296         $cats->get('/nyan')->to(action => 'nyan');
297         $cats->get('/lol');
298
299       With a few common prefixes you can also greatly improve the routing
300       performance of applications with many routes, because children are only
301       tried if the prefix matched first.
302
303   Special stash values
304       When the dispatcher sees "controller" and "action" values in the stash
305       it will always try to turn them into a class and method to dispatch to.
306       The "controller" value gets converted from "snake_case" to "CamelCase"
307       using "camelize" in Mojo::Util and appended to one or more namespaces,
308       defaulting to a controller namespace based on the application class
309       ("MyApp::Controller"), as well as the bare application class ("MyApp"),
310       and these namespaces are searched in that order. The action value is
311       not changed at all, so both values are case-sensitive.
312
313         # Application
314         package MyApp;
315         use Mojo::Base 'Mojolicious', -signatures;
316
317         sub startup ($self) {
318           # /bye -> MyApp::Controller::Foo->bye
319           $self->routes->get('/bye')->to(controller => 'foo', action => 'bye');
320         }
321
322         1;
323
324         # Controller
325         package MyApp::Controller::Foo;
326         use Mojo::Base 'Mojolicious::Controller', -signatures;
327
328         # Action
329         sub bye ($self) {
330           # Render response
331           $self->render(text => 'Good bye.');
332         }
333
334         1;
335
336       Controller classes are perfect for organizing code in larger projects.
337       There are more dispatch strategies, but because controllers are the
338       most commonly used ones they also got a special shortcut in the form of
339       "controller#action".
340
341         # /bye -> {controller => 'foo', action => 'bye', mymessage => 'Bye'}
342         $r->get('/bye')->to('foo#bye', mymessage => 'Bye');
343
344       During camelization "-" characters get replaced with "::", this allows
345       multi-level "controller" hierarchies.
346
347         # / -> MyApp::Controller::Foo::Bar->hi
348         $r->get('/')->to('foo-bar#hi');
349
350       You can also just specify the "controller" in CamelCase form instead of
351       snake_case.
352
353         # / -> MyApp::Controller::Foo::Bar->hi
354         $r->get('/')->to('Foo::Bar#hi');
355
356       For security reasons the dispatcher will always check if the
357       "controller" is actually a subclass of Mojolicious::Controller or Mojo
358       before dispatching to it.
359
360   Namespaces
361       You can use the "namespace" stash value to change the namespace of a
362       whole route with all its children.
363
364         # /bye -> MyApp::MyController::Foo::Bar->bye
365         $r->get('/bye')->to(namespace => 'MyApp::MyController::Foo::Bar', action => 'bye');
366
367       The "controller" is always converted from "snake_case" to "CamelCase"
368       with "camelize" in Mojo::Util, and then appended to this "namespace".
369
370         # /bye -> MyApp::MyController::Foo::Bar->bye
371         $r->get('/bye')->to('foo-bar#bye', namespace => 'MyApp::MyController');
372
373         # /hey -> MyApp::MyController::Foo::Bar->hey
374         $r->get('/hey')->to('Foo::Bar#hey', namespace => 'MyApp::MyController');
375
376       You can also change the default namespaces for all routes in the
377       application with the router attribute "namespaces" in
378       Mojolicious::Routes, which usually defaults to a namespace based on the
379       application class ("MyApp::Controller"), as well as the bare
380       application class ("MyApp").
381
382         $r->namespaces(['MyApp::MyController']);
383
384   Route to callback
385       The "cb" stash value, which won't be inherited by nested routes, can be
386       used to bypass controllers and execute a callback instead.
387
388         $r->get('/bye')->to(cb => sub ($c) {
389           $c->render(text => 'Good bye.');
390         });
391
392       But just like in Mojolicious::Lite you can also pass the callback
393       directly, which usually looks much better.
394
395         $r->get('/bye' => sub ($c) {
396           $c->render(text => 'Good bye.');
397         });
398
399   Named routes
400       Naming your routes will allow backreferencing in many methods and
401       helpers throughout the whole framework, most of which internally rely
402       on "url_for" in Mojolicious::Controller for this.
403
404         # /foo/marcus -> {controller => 'foo', action => 'bar', user => 'marcus'}
405         $r->get('/foo/:user')->to('foo#bar')->name('baz');
406
407         # Generate URL "/foo/marcus" for route "baz" (in previous request context)
408         my $url = $c->url_for('baz');
409
410         # Generate URL "/foo/jan" for route "baz"
411         my $url = $c->url_for('baz', user => 'jan');
412
413         # Generate URL "http://127.0.0.1:3000/foo/jan" for route "baz"
414         my $url = $c->url_for('baz', user => 'jan')->to_abs;
415
416       You can assign a name with "name" in Mojolicious::Routes::Route, or let
417       the router generate one automatically, which would be equal to the
418       route itself without non-word characters, custom names have a higher
419       precedence though.
420
421         # /foo/bar ("foobar")
422         $r->get('/foo/bar')->to('test#stuff');
423
424         # Generate URL "/foo/bar"
425         my $url = $c->url_for('foobar');
426
427       To refer to the current route you can use the reserved name "current"
428       or no name at all.
429
430         # Generate URL for current route
431         my $url = $c->url_for('current');
432         my $url = $c->url_for;
433
434       To check or get the name of the current route you can use the helper
435       "current_route" in Mojolicious::Plugin::DefaultHelpers.
436
437         # Name for current route
438         my $name = $c->current_route;
439
440         # Check route name in code shared by multiple routes
441         $c->stash(button => 'green') if $c->current_route('login');
442
443   Optional placeholders
444       Extracted placeholder values will simply redefine older stash values if
445       they already exist.
446
447         # /bye -> {controller => 'foo', action => 'bar', mymessage => 'bye'}
448         # /hey -> {controller => 'foo', action => 'bar', mymessage => 'hey'}
449         $r->get('/:mymessage')->to('foo#bar', mymessage => 'hi');
450
451       One more interesting effect, a placeholder automatically becomes
452       optional if there is already a stash value of the same name present,
453       this works similar to the regular expression "([^/.]+)?".
454
455         # / -> {controller => 'foo', action => 'bar', mymessage => 'hi'}
456         $r->get('/:mymessage')->to('foo#bar', mymessage => 'hi');
457
458         # /test/123     -> {controller => 'foo', action => 'bar', mymessage => 'hi'}
459         # /test/bye/123 -> {controller => 'foo', action => 'bar', mymessage => 'bye'}
460         $r->get('/test/:mymessage/123')->to('foo#bar', mymessage => 'hi');
461
462       And if two optional placeholders are only separated by a slash, that
463       slash can become optional as well.
464
465         # /           -> {controller => 'foo',   action => 'bar'}
466         # /users      -> {controller => 'users', action => 'bar'}
467         # /users/list -> {controller => 'users', action => 'list'}
468         $r->get('/:controller/:action')->to('foo#bar');
469
470       Special stash values like "controller" and "action" can also be
471       placeholders, which is very convenient especially during development,
472       but should only be used very carefully, because every controller method
473       becomes a potential route.  All uppercase methods as well as those
474       starting with an underscore are automatically hidden from the router
475       and you can use "hide" in Mojolicious::Routes to add additional ones.
476
477         # Hide "create" method in all controllers
478         $r->hide('create');
479
480       This has already been done for all attributes and methods from
481       Mojolicious::Controller.
482
483   Restrictive placeholders
484       A very easy way to make placeholders more restrictive are alternatives,
485       you just make a list of possible values, which then work similar to the
486       regular expression "(bender|leela)".
487
488         # /fry    -> undef
489         # /bender -> {controller => 'foo', action => 'bar', name => 'bender'}
490         # /leela  -> {controller => 'foo', action => 'bar', name => 'leela'}
491         $r->get('/:name' => [name => ['bender', 'leela']])->to('foo#bar');
492
493       You can also adjust the regular expressions behind placeholders
494       directly, just make sure not to use "^" and "$" or capturing groups
495       "(...)", because placeholders become part of a larger regular
496       expression internally, non-capturing groups "(?:...)" are fine though.
497
498         # /23   -> {controller => 'foo', action => 'bar', number => 23}
499         # /test -> undef
500         $r->get('/:number' => [number => qr/\d+/])->to('foo#bar');
501
502         # /23   -> undef
503         # /test -> {controller => 'foo', action => 'bar', name => 'test'}
504         $r->get('/:name' => [name => qr/[a-zA-Z]+/])->to('foo#bar');
505
506       This way you get easily readable routes and the raw power of regular
507       expressions.
508
509   Placeholder types
510       And if you have multiple routes using restrictive placeholders you can
511       also turn them into placeholder types with "add_type" in
512       Mojolicious::Routes.
513
514         # A type with alternatives
515         $r->add_type(futurama_name => ['bender', 'leela']);
516
517         # /fry    -> undef
518         # /bender -> {controller => 'foo', action => 'bar', name => 'bender'}
519         # /leela  -> {controller => 'foo', action => 'bar', name => 'leela'}
520         $r->get('/<name:futurama_name>')->to('foo#bar');
521
522       Placeholder types work just like restrictive placeholders, they are
523       just reusable with the "<placeholder:type>" notation.
524
525         # A type adjusting the regular expression
526         $r->add_type(upper => qr/[A-Z]+/);
527
528         # /user/ROOT -> {controller => 'users', action => 'show', name => 'ROOT'}
529         # /user/root -> undef
530         # /user/23   -> undef
531         $r->get('/user/<name:upper>')->to('users#show');
532
533       Some types like "num" are used so commonly that they are available by
534       default.
535
536         # /article/12   -> {controller => 'article', action => 'show', id => 12}
537         # /article/test -> undef
538         $r->get('/article/<id:num>')->to('articles#show');
539
540       For a full list of available placeholder types see also "TYPES" in
541       Mojolicious::Routes.
542
543   Introspection
544       The command Mojolicious::Command::routes can be used from the command
545       line to list all available routes together with names and underlying
546       regular expressions.
547
548         $ ./myapp.pl routes -v
549         /foo/:name  ....  POST  fooname  ^/foo/([^/.]+)/?(?:\.([^/]+))?$
550         /bar        ..U.  *     bar      ^/bar
551           +/baz     ...W  GET   baz      ^/baz/?(?:\.([^/]+))?$
552         /yada       ....  *     yada     ^/yada/?(?:\.([^/]+))?$
553
554   Under
555       To share code with multiple nested routes you can use "under" in
556       Mojolicious::Routes::Route, because unlike normal nested routes, the
557       routes generated with it have their own intermediate destination and
558       result in additional dispatch cycles when they match.
559
560         # /foo     -> undef
561         # /foo/bar -> {controller => 'foo', action => 'baz'}
562         #             {controller => 'foo', action => 'bar'}
563         my $foo = $r->under('/foo')->to('foo#baz');
564         $foo->get('/bar')->to('#bar');
565
566       The actual action code for this destination needs to return a true
567       value or the dispatch chain will be broken, this can be a very powerful
568       tool for authentication.
569
570         # /blackjack -> {cb => sub {...}}
571         #               {controller => 'hideout', action => 'blackjack'}
572         my $auth = $r->under('/' => sub ($c) {
573
574           # Authenticated
575           return 1 if $c->req->headers->header('X-Bender');
576
577           # Not authenticated
578           $c->render(text => "You're not Bender.", status => 401);
579           return undef;
580         });
581         $auth->get('/blackjack')->to('hideout#blackjack');
582
583       Broken dispatch chains can be continued by calling "continue" in
584       Mojolicious::Controller, this allows for example, non-blocking
585       operations to finish before reaching the next dispatch cycle.
586
587         my $maybe = $r->under('/maybe' => sub ($c) {
588
589           # Wait 3 seconds and then give visitors a 50% chance to continue
590           Mojo::IOLoop->timer(3 => sub {
591
592             # Loser
593             return $c->render(text => 'No luck.') unless int rand 2;
594
595             # Winner
596             $c->continue;
597           });
598
599           return undef;
600         });
601         $maybe->get('/')->to('maybe#winner');
602
603       Every destination is just a snapshot of the stash at the time the route
604       matched, and only the "format" value is shared by all of them. For a
605       little more power you can introspect the preceding and succeeding
606       destinations with "match" in Mojolicious::Controller.
607
608         # Action of the fourth dispatch cycle
609         my $action = $c->match->stack->[3]{action};
610
611   Formats
612       File extensions like ".html" and ".txt" at the end of a route are
613       automatically detected and stored in the stash value "format".
614
615         # /foo      -> {controller => 'foo', action => 'bar'}
616         # /foo.html -> {controller => 'foo', action => 'bar', format => 'html'}
617         # /foo.txt  -> {controller => 'foo', action => 'bar', format => 'txt'}
618         $r->get('/foo')->to('foo#bar');
619
620       This for example, allows multiple templates in different formats to
621       share the same action code. Restrictive placeholders can also be used
622       to limit the allowed formats.
623
624         # /foo.txt -> undef
625         # /foo.rss -> {controller => 'foo', action => 'bar', format => 'rss'}
626         # /foo.xml -> {controller => 'foo', action => 'bar', format => 'xml'}
627         $r->get('/foo' => [format => ['rss', 'xml']])->to('foo#bar');
628
629       A "format" value can also be passed to "url_for" in
630       Mojolicious::Controller.
631
632         # /foo/23.txt -> {controller => 'foo', action => 'bar', id => 23, format => 'txt'}
633         $r->get('/foo/:id')->to('foo#bar')->name('baz');
634
635         # Generate URL "/foo/24.txt" for route "baz"
636         my $url = $c->url_for('baz', id => 24, format => 'txt');
637
638       Or you can just disable format detection with a special type of
639       restrictive placeholder, which gets inherited by nested routes, and
640       then re-enable it on demand.
641
642         # /foo      -> {controller => 'foo', action => 'bar'}
643         # /foo.html -> undef
644         $r->get('/foo' => [format => 0])->to('foo#bar');
645
646         # /foo      -> {controller => 'foo', action => 'bar'}
647         # /foo.html -> undef
648         # /baz      -> undef
649         # /baz.txt  -> {controller => 'baz', action => 'yada', format => 'txt'}
650         # /baz.html -> {controller => 'baz', action => 'yada', format => 'html'}
651         # /baz.xml  -> undef
652         my $inactive = $r->under([format => 0]);
653         $inactive->get('/foo')->to('foo#bar');
654         $inactive->get('/baz' => [format => ['txt', 'html']])->to('baz#yada');
655
656   WebSockets
657       With the method "websocket" in Mojolicious::Routes::Route you can
658       restrict access to WebSocket handshakes, which are normal "GET"
659       requests with some additional information.
660
661         # /echo (WebSocket handshake)
662         $r->websocket('/echo')->to('foo#echo');
663
664         # Controller
665         package MyApp::Controller::Foo;
666         use Mojo::Base 'Mojolicious::Controller', -signatures;
667
668         # Action
669         sub echo ($self) {
670           $self->on(message => sub ($self, $msg) {
671             $self->send("echo: $msg");
672           });
673         }
674
675         1;
676
677       The connection gets established when you respond to the WebSocket
678       handshake request with a 101 response status, which happens
679       automatically if you subscribe to an event with "on" in
680       Mojolicious::Controller or send a message with "send" in
681       Mojolicious::Controller right away.
682
683         GET /echo HTTP/1.1
684         Host: mojolicious.org
685         User-Agent: Mojolicious (Perl)
686         Connection: Upgrade
687         Upgrade: websocket
688         Sec-WebSocket-Key: IDM3ODE4NDk2MjA1OTcxOQ==
689         Sec-WebSocket-Version: 13
690
691         HTTP/1.1 101 Switching Protocols
692         Server: Mojolicious (Perl)
693         Date: Tue, 03 Feb 2015 17:08:24 GMT
694         Connection: Upgrade
695         Upgrade: websocket
696         Sec-WebSocket-Accept: SWsp5N2iNxPbHlcOTIw8ERvyVPY=
697
698   Catch-all route
699       Since routes match in the order in which they were defined, you can
700       catch all requests that did not match in your last route with an
701       optional wildcard placeholder.
702
703         # * /*
704         $r->any('/*whatever' => {whatever => ''} => sub ($c) {
705           my $whatever = $c->param('whatever');
706           $c->render(text => "/$whatever did not match.", status => 404);
707         });
708
709   Conditions
710       Conditions such as "headers", "agent" and "host" from
711       Mojolicious::Plugin::HeaderCondition can be applied to any route with
712       the method "requires" in Mojolicious::Routes::Route, and allow even
713       more powerful route constructs.
714
715         # / (Origin: http://perl.org)
716         $r->get('/')->requires(headers => {Origin => qr/perl\.org/})->to('foo#bar');
717
718         # / (Firefox)
719         $r->get('/')->requires(agent => qr/Firefox/)->to('browser-test#firefox');
720
721         # / (Internet Explorer)
722         $r->get('/')->requires(agent => qr/Internet Explorer/)->to('browser-test#ie');
723
724         # http://docs.mojolicious.org/Mojolicious
725         $r->get('/')->requires(host => 'docs.mojolicious.org')->to('perldoc#index');
726
727       Just be aware that conditions are too complex for the routing cache,
728       which normally speeds up recurring requests, and can therefore reduce
729       performance.
730
731   Hooks
732       Hooks operate outside the routing system and allow you to extend the
733       framework itself by sharing code with all requests indiscriminately
734       through "hook" in Mojolicious, which makes them a very powerful tool
735       especially for plugins.
736
737         # Application
738         package MyApp;
739         use Mojo::Base 'Mojolicious', -signatures;
740
741         sub startup ($self) {
742
743           # Check all requests for a "/test" prefix
744           $self->hook(before_dispatch => sub ($c) {
745             $c->render(text => 'This request did not reach the router.') if $c->req->url->path->contains('/test');
746           });
747
748           # These will not be reached if the hook above renders a response
749           my $r = $self->routes;
750           $r->get('/welcome')->to('foo#welcome');
751           $r->post('/bye')->to('foo#bye');
752         }
753
754         1;
755
756       Post-processing the response to add or remove headers is a very common
757       use.
758
759         # Make sure static files are cached
760         $app->hook(after_static => sub ($c) {
761           $c->res->headers->cache_control('max-age=3600, must-revalidate');
762         });
763
764         # Remove a default header
765         $app->hook(after_dispatch => sub ($c) {
766           $c->res->headers->remove('Server');
767         });
768
769       Same for pre-processing the request.
770
771         # Choose template variant based on request headers
772         $app->hook(before_dispatch => sub ($c) {
773           return unless my $agent = $c->req->headers->user_agent;
774           $c->stash(variant => 'ie') if $agent =~ /Internet Explorer/;
775         });
776
777       Or more advanced extensions to add monitoring to your application.
778
779         # Forward exceptions to a web service
780         $app->hook(after_dispatch => sub ($c) {
781           return unless my $e = $c->stash('exception');
782           $c->ua->post('https://example.com/bugs' => form => {exception => $e});
783         });
784
785       You can even extend much of the core functionality.
786
787         # Make controller object available to actions as $_
788         $app->hook(around_action => sub ($next, $c, $action, $last) {
789           local $_ = $c;
790           return $next->();
791         });
792
793         # Pass route name as argument to actions
794         $app->hook(around_action => sub ($next, $c, $action, $last) {
795           return $c->$action($c->current_route);
796         });
797
798       For a full list of available hooks see "HOOKS" in Mojolicious.
799

ADVANCED

801       Less commonly used and more powerful features.
802
803   Shortcuts
804       To make route generation more expressive, you can also add your own
805       shortcuts with "add_shortcut" in Mojolicious::Routes.
806
807         # Simple "resource" shortcut
808         $r->add_shortcut(resource => sub ($r, $name) {
809
810           # Prefix for resource
811           my $resource = $r->any("/$name")->to("$name#");
812
813           # Render a list of resources
814           $resource->get('/')->to('#index')->name($name);
815
816           # Render a form to create a new resource (submitted to "store")
817           $resource->get('/create')->to('#create')->name("create_$name");
818
819           # Store newly created resource (submitted by "create")
820           $resource->post->to('#store')->name("store_$name");
821
822           # Render a specific resource
823           $resource->get('/:id')->to('#show')->name("show_$name");
824
825           # Render a form to edit a resource (submitted to "update")
826           $resource->get('/:id/edit')->to('#edit')->name("edit_$name");
827
828           # Store updated resource (submitted by "edit")
829           $resource->put('/:id')->to('#update')->name("update_$name");
830
831           # Remove a resource
832           $resource->delete('/:id')->to('#remove')->name("remove_$name");
833
834           return $resource;
835         });
836
837         # GET /users         -> {controller => 'users', action => 'index'}
838         # GET /users/create  -> {controller => 'users', action => 'create'}
839         # POST /users        -> {controller => 'users', action => 'store'}
840         # GET /users/23      -> {controller => 'users', action => 'show', id => 23}
841         # GET /users/23/edit -> {controller => 'users', action => 'edit', id => 23}
842         # PUT /users/23      -> {controller => 'users', action => 'update', id => 23}
843         # DELETE /users/23   -> {controller => 'users', action => 'remove', id => 23}
844         $r->resource('users');
845
846   Rearranging routes
847       From application startup until the first request has arrived, all
848       routes can still be moved around or even removed with methods like
849       "add_child" in Mojolicious::Routes::Route and "remove" in
850       Mojolicious::Routes::Route.
851
852         # GET /example/show -> {controller => 'example', action => 'show'}
853         my $show = $r->get('/show')->to('example#show');
854         $r->any('/example')->add_child($show);
855
856         # Nothing
857         $r->get('/secrets/show')->to('secrets#show')->name('show_secrets');
858         $r->find('show_secrets')->remove;
859
860       Especially for rearranging routes created by plugins this can be very
861       useful, to find routes by their name you can use "find" in
862       Mojolicious::Routes::Route.
863
864         # GET /example/test -> {controller => 'example', action => 'test'}
865         $r->get('/something/else')->to('something#else')->name('test');
866         my $test = $r->find('test');
867         $test->pattern->parse('/example/test');
868         $test->pattern->defaults({controller => 'example', action => 'test'});
869
870       Even the route pattern and destination can still be changed with
871       "parse" in Mojolicious::Routes::Pattern and "defaults" in
872       Mojolicious::Routes::Pattern.
873
874   Adding conditions
875       You can also add your own conditions with the method "add_condition" in
876       Mojolicious::Routes. All conditions are basically router plugins that
877       run every time a new request arrives, and which need to return a true
878       value for the route to match.
879
880         # A condition that randomly allows a route to match
881         $r->add_condition(random => sub ($route, $c, $captures, $num) {
882
883           # Loser
884           return undef if int rand $num;
885
886           # Winner
887           return 1;
888         });
889
890         # /maybe (25% chance)
891         $r->get('/maybe')->requires(random => 4)->to('foo#bar');
892
893       Use whatever request information you need.
894
895         # A condition to check query parameters (useful for mock web services)
896         $r->add_condition(query => sub ($route, $c, $captures, $hash) {
897
898           for my $key (keys %$hash) {
899             my $param = $c->req->url->query->param($key);
900             return undef unless defined $param && $param eq $hash->{$key};
901           }
902
903           return 1;
904         });
905
906         # /hello?to=world&test=1
907         $r->get('/hello')->requires(query => {test => 1, to => 'world'})->to('foo#bar');
908
909   Condition plugins
910       You can also package your conditions as reusable plugins.
911
912         # Plugin
913         package Mojolicious::Plugin::WerewolfCondition;
914         use Mojo::Base 'Mojolicious::Plugin', -signatures;
915
916         use Astro::MoonPhase;
917
918         sub register ($self, $app, $conf) {
919
920           # Add "werewolf" condition
921           $app->routes->add_condition(werewolf => sub ($route, $c, $captures, $days) {
922
923             # Keep the werewolves out!
924             return undef if abs(14 - (phase(time))[2]) > ($days / 2);
925
926             # It's ok, no werewolf
927             return 1;
928           });
929         }
930
931         1;
932
933       Now just load the plugin and you are ready to use the condition in all
934       your applications.
935
936         # Application
937         package MyApp;
938         use Mojo::Base 'Mojolicious', -signatures;
939
940         sub startup ($self) {
941
942           # Plugin
943           $self->plugin('WerewolfCondition');
944
945           # /hideout (keep them out for 4 days after full moon)
946           $self->routes->get('/hideout')->requires(werewolf => 4)->to(controller => 'foo', action => 'bar');
947         }
948
949         1;
950
951   Mount applications
952       The easiest way to embed one application into another is
953       Mojolicious::Plugin::Mount, which allows you to mount whole self-
954       contained applications under a domain and/or prefix.
955
956         use Mojolicious::Lite -signatures;
957
958         # Whole application mounted under "/prefix"
959         plugin Mount => {'/prefix' => '/home/sri/myapp/script/myapp'};
960
961         # Mount application with subdomain
962         plugin Mount => {'test.example.com' => '/home/sri/myapp2.pl'};
963
964         # Normal route
965         get '/' => sub ($c) {
966           $c->render(text => 'Hello World!');
967         };
968
969         app->start;
970
971   Embed applications
972       For a little more power you can also embed applications by using them
973       instead of a controller. This allows for example, the use of the
974       Mojolicious::Lite domain specific language in normal Mojolicious
975       controllers.
976
977         # Controller
978         package MyApp::Controller::Bar;
979         use Mojolicious::Lite -signatures;
980
981         # /hello
982         get '/hello' => sub ($c) {
983           my $name = $c->param('name');
984           $c->render(text => "Hello $name.");
985         };
986
987         1;
988
989       With the attribute "partial" in Mojolicious::Routes::Route, you can
990       allow the route to partially match and use only the remaining path in
991       the embedded application, the base path will be passed along in the
992       "path" stash value.
993
994         # /foo/*
995         $r->any('/foo')->partial(1)->to('bar#', name => 'Mojo');
996
997       A minimal embeddable application is nothing more than a subclass of
998       Mojolicious, containing a "handler" method accepting
999       Mojolicious::Controller objects.
1000
1001         package MyApp::Controller::Bar;
1002         use Mojo::Base 'Mojolicious', -signatures;
1003
1004         sub handler ($self, $c) {
1005           $c->res->code(200);
1006           my $name = $c->param('name');
1007           $c->res->body("Hello $name.");
1008         }
1009
1010         1;
1011
1012       The host application will only share very little information with the
1013       embedded application through the stash. So you cannot currently use
1014       route placeholders in routes leading to embedded applications, since
1015       that would cause problems with "url_for" in Mojolicious::Controller.
1016
1017   Application plugins
1018       You can even package applications as self-contained reusable plugins.
1019
1020         # Plugin
1021         package Mojolicious::Plugin::MyEmbeddedApp;
1022         use Mojo::Base 'Mojolicious::Plugin', -signatures;
1023
1024         sub register ($self, $app, $conf) {
1025
1026           # Automatically add route
1027           $app->routes->any('/foo')->partial(1)->to(app => EmbeddedApp::app());
1028         }
1029
1030         package EmbeddedApp;
1031         use Mojolicious::Lite;
1032
1033         get '/bar' => 'bar';
1034
1035         1;
1036         __DATA__
1037         @@ bar.html.ep
1038         Hello World!
1039
1040       The "app" stash value, which won't be inherited by nested routes, can
1041       be used for already instantiated applications.  Now just load the
1042       plugin and you're done.
1043
1044         # Application
1045         package MyApp;
1046         use Mojo::Base 'Mojolicious', -signatures;
1047
1048         sub startup ($self) {
1049
1050           # Plugin
1051           $self->plugin('MyEmbeddedApp');
1052         }
1053
1054         1;
1055

MORE

1057       You can continue with Mojolicious::Guides now or take a look at the
1058       Mojolicious wiki <https://github.com/mojolicious/mojo/wiki>, which
1059       contains a lot more documentation and examples by many different
1060       authors.
1061

SUPPORT

1063       If you have any questions the documentation might not yet answer, don't
1064       hesitate to ask in the Forum <https://forum.mojolicious.org> or the
1065       official IRC channel "#mojo" on "chat.freenode.net" (chat now!
1066       <https://webchat.freenode.net/#mojo>).
1067
1068
1069
1070perl v5.32.1                      2021-02-07   Mojolicious::Guides::Routing(3)
Impressum