1Mojolicious::Guides::RoUusteirngC(o3n)tributed Perl DocuMmoejnotlaitciioonus::Guides::Routing(3)
2
3
4
6 Mojolicious::Guides::Routing - Routing requests
7
9 This document contains a simple and fun introduction to the Mojolicious
10 router and its underlying concepts.
11
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/show/(\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/show/: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/:action/:id
64
65 A fundamental concept of the Mojolicious router is that extracted
66 placeholder values are turned into a hash.
67
68 /user/show/23 -> /user/:action/:id -> {action => 'show', 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/show/:id -> qr/(?-xism:^\/user\/show\/([^\/.]+))/
76
77 A trailing slash in the path is always optional.
78
79 /user/show/23/ -> /user/:action/:id -> {action => 'show', 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
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';
162
163 sub startup {
164 my $self = shift;
165
166 # Router
167 my $r = $self->routes;
168
169 # Route
170 $r->get('/welcome')->to(controller => 'foo', action => 'welcome');
171 }
172
173 1;
174
175 The minimal route above will load and instantiate the class
176 "MyApp::Controller::Foo" and call its "welcome" method. Routes are
177 usually configured in the "startup" method of the application class,
178 but the router can be accessed from everywhere (even at runtime).
179
180 # Controller
181 package MyApp::Controller::Foo;
182 use Mojo::Base 'Mojolicious::Controller';
183
184 # Action
185 sub welcome {
186 my $self = shift;
187
188 # Render response
189 $self->render(text => 'Hello there.');
190 }
191
192 1;
193
194 All routes match in the same order in which they were defined, and
195 matching stops as soon as a suitable route has been found. So you can
196 improve the routing performance by declaring your most frequently
197 accessed routes first. A routing cache will also be used automatically
198 to handle sudden traffic spikes more gracefully.
199
200 Routing destination
201 After you start a new route with methods like "get" in
202 Mojolicious::Routes::Route, you can also give it a destination in the
203 form of a hash using the chained method "to" in
204 Mojolicious::Routes::Route.
205
206 # /welcome -> {controller => 'foo', action => 'welcome'}
207 $r->get('/welcome')->to(controller => 'foo', action => 'welcome');
208
209 Now if the route matches an incoming request it will use the content of
210 this hash to try and find appropriate code to generate a response.
211
212 HTTP methods
213 There are already shortcuts for the most common HTTP request methods
214 like "post" in Mojolicious::Routes::Route, and for more control "any"
215 in Mojolicious::Routes::Route accepts an optional array reference with
216 arbitrary request methods as first argument.
217
218 # PUT /hello -> undef
219 # GET /hello -> {controller => 'foo', action => 'hello'}
220 $r->get('/hello')->to(controller => 'foo', action => 'hello');
221
222 # PUT /hello -> {controller => 'foo', action => 'hello'}
223 $r->put('/hello')->to(controller => 'foo', action => 'hello');
224
225 # POST /hello -> {controller => 'foo', action => 'hello'}
226 $r->post('/hello')->to(controller => 'foo', action => 'hello');
227
228 # GET|POST /bye -> {controller => 'foo', action => 'bye'}
229 $r->any(['GET', 'POST'] => '/bye')->to(controller => 'foo', action => 'bye');
230
231 # * /whatever -> {controller => 'foo', action => 'whatever'}
232 $r->any('/whatever')->to(controller => 'foo', action => 'whatever');
233
234 There is one small exception, "HEAD" requests are considered equal to
235 "GET", but content will not be sent with the response even if it is
236 present.
237
238 # GET /test -> {controller => 'bar', action => 'test'}
239 # HEAD /test -> {controller => 'bar', action => 'test'}
240 $r->get('/test')->to(controller => 'bar', action => 'test');
241
242 You can also use the "_method" query parameter to override the request
243 method. This can be very useful when submitting forms with browsers
244 that only support "GET" and "POST".
245
246 # PUT /stuff -> {controller => 'baz', action => 'stuff'}
247 # POST /stuff?_method=PUT -> {controller => 'baz', action => 'stuff'}
248 $r->put('/stuff')->to(controller => 'baz', action => 'stuff');
249
250 IRIs
251 IRIs are handled transparently, that means paths are guaranteed to be
252 unescaped and decoded from bytes to characters.
253
254 # GET /☃ (Unicode snowman) -> {controller => 'foo', action => 'snowman'}
255 $r->get('/☃')->to(controller => 'foo', action => 'snowman');
256
257 Stash
258 The generated hash of a matching route is actually the center of the
259 whole Mojolicious request cycle. We call it the stash, and it persists
260 until a response has been generated.
261
262 # /bye -> {controller => 'foo', action => 'bye', mymessage => 'Bye'}
263 $r->get('/bye')
264 ->to(controller => 'foo', action => 'bye', mymessage => 'Bye');
265
266 There are a few stash values with special meaning, such as "controller"
267 and "action", but you can generally fill it with whatever data you need
268 to generate a response. Once dispatched the whole stash content can be
269 changed at any time.
270
271 sub bye {
272 my $self = shift;
273
274 # Get message from stash
275 my $msg = $self->stash('mymessage');
276
277 # Change message in stash
278 $self->stash(mymessage => 'Welcome');
279 }
280
281 For a full list of reserved stash values see "stash" in
282 Mojolicious::Controller.
283
284 Nested routes
285 It is also possible to build tree structures from routes to remove
286 repetitive code. A route with children can't match on its own though,
287 only the actual endpoints of these nested routes can.
288
289 # /foo -> undef
290 # /foo/bar -> {controller => 'foo', action => 'bar'}
291 my $foo = $r->any('/foo')->to(controller => 'foo');
292 $foo->get('/bar')->to(action => 'bar');
293
294 The stash is simply inherited from route to route and newer values
295 override old ones.
296
297 # /cats -> {controller => 'cats', action => 'index'}
298 # /cats/nyan -> {controller => 'cats', action => 'nyan'}
299 # /cats/lol -> {controller => 'cats', action => 'default'}
300 my $cats = $r->any('/cats')->to(controller => 'cats', action => 'default');
301 $cats->get('/')->to(action => 'index');
302 $cats->get('/nyan')->to(action => 'nyan');
303 $cats->get('/lol');
304
305 With a few common prefixes you can also greatly improve the routing
306 performance of applications with many routes, because children are only
307 tried if the prefix matched first.
308
309 Special stash values
310 When the dispatcher sees "controller" and "action" values in the stash
311 it will always try to turn them into a class and method to dispatch to.
312 The "controller" value gets converted from "snake_case" to "CamelCase"
313 using "camelize" in Mojo::Util and appended to one or more namespaces,
314 defaulting to a controller namespace based on the application class
315 ("MyApp::Controller"), as well as the bare application class ("MyApp"),
316 and these namespaces are searched in that order. The action value is
317 not changed at all, so both values are case-sensitive.
318
319 # Application
320 package MyApp;
321 use Mojo::Base 'Mojolicious';
322
323 sub startup {
324 my $self = shift;
325
326 # /bye -> MyApp::Controller::Foo->bye
327 $self->routes->get('/bye')->to(controller => 'foo', action => 'bye');
328 }
329
330 1;
331
332 # Controller
333 package MyApp::Controller::Foo;
334 use Mojo::Base 'Mojolicious::Controller';
335
336 # Action
337 sub bye {
338 my $self = shift;
339
340 # Render response
341 $self->render(text => 'Good bye.');
342 }
343
344 1;
345
346 Controller classes are perfect for organizing code in larger projects.
347 There are more dispatch strategies, but because controllers are the
348 most commonly used ones they also got a special shortcut in the form of
349 "controller#action".
350
351 # /bye -> {controller => 'foo', action => 'bye', mymessage => 'Bye'}
352 $r->get('/bye')->to('foo#bye', mymessage => 'Bye');
353
354 During camelization "-" characters get replaced with "::", this allows
355 multi-level "controller" hierarchies.
356
357 # / -> MyApp::Controller::Foo::Bar->hi
358 $r->get('/')->to('foo-bar#hi');
359
360 You can also just specify the "controller" in CamelCase form instead of
361 snake_case.
362
363 # / -> MyApp::Controller::Foo::Bar->hi
364 $r->get('/')->to('Foo::Bar#hi');
365
366 For security reasons the dispatcher will always check if the
367 "controller" is actually a subclass of Mojolicious::Controller or Mojo
368 before dispatching to it.
369
370 Namespaces
371 You can use the "namespace" stash value to change the namespace of a
372 whole route with all its children.
373
374 # /bye -> MyApp::MyController::Foo::Bar->bye
375 $r->get('/bye')
376 ->to(namespace => 'MyApp::MyController::Foo::Bar', action => 'bye');
377
378 The "controller" is always converted from "snake_case" to "CamelCase"
379 with "camelize" in Mojo::Util, and then appended to this "namespace".
380
381 # /bye -> MyApp::MyController::Foo::Bar->bye
382 $r->get('/bye')->to('foo-bar#bye', namespace => 'MyApp::MyController');
383
384 # /hey -> MyApp::MyController::Foo::Bar->hey
385 $r->get('/hey')->to('Foo::Bar#hey', namespace => 'MyApp::MyController');
386
387 You can also change the default namespaces for all routes in the
388 application with the router attribute "namespaces" in
389 Mojolicious::Routes, which usually defaults to a namespace based on the
390 application class ("MyApp::Controller"), as well as the bare
391 application class ("MyApp").
392
393 $r->namespaces(['MyApp::MyController']);
394
395 Route to callback
396 The "cb" stash value, which won't be inherited by nested routes, can be
397 used to bypass controllers and execute a callback instead.
398
399 $r->get('/bye')->to(cb => sub {
400 my $c = shift;
401 $c->render(text => 'Good bye.');
402 });
403
404 But just like in Mojolicious::Lite you can also pass the callback
405 directly, which usually looks much better.
406
407 $r->get('/bye' => sub {
408 my $c = shift;
409 $c->render(text => 'Good bye.');
410 });
411
412 Named routes
413 Naming your routes will allow backreferencing in many methods and
414 helpers throughout the whole framework, most of which internally rely
415 on "url_for" in Mojolicious::Controller for this.
416
417 # /foo/marcus -> {controller => 'foo', action => 'bar', user => 'marcus'}
418 $r->get('/foo/:user')->to('foo#bar')->name('baz');
419
420 # Generate URL "/foo/marcus" for route "baz"
421 my $url = $c->url_for('baz');
422
423 # Generate URL "/foo/jan" for route "baz"
424 my $url = $c->url_for('baz', user => 'jan');
425
426 # Generate URL "http://127.0.0.1:3000/foo/jan" for route "baz"
427 my $url = $c->url_for('baz', user => 'jan')->to_abs;
428
429 You can assign a name with "name" in Mojolicious::Routes::Route, or let
430 the router generate one automatically, which would be equal to the
431 route itself without non-word characters, custom names have a higher
432 precedence though.
433
434 # /foo/bar ("foobar")
435 $r->get('/foo/bar')->to('test#stuff');
436
437 # Generate URL "/foo/bar"
438 my $url = $c->url_for('foobar');
439
440 To refer to the current route you can use the reserved name "current"
441 or no name at all.
442
443 # Generate URL for current route
444 my $url = $c->url_for('current');
445 my $url = $c->url_for;
446
447 To check or get the name of the current route you can use the helper
448 "current_route" in Mojolicious::Plugin::DefaultHelpers.
449
450 # Name for current route
451 my $name = $c->current_route;
452
453 # Check route name in code shared by multiple routes
454 $c->stash(button => 'green') if $c->current_route('login');
455
456 Optional placeholders
457 Extracted placeholder values will simply redefine older stash values if
458 they already exist.
459
460 # /bye -> {controller => 'foo', action => 'bar', mymessage => 'bye'}
461 # /hey -> {controller => 'foo', action => 'bar', mymessage => 'hey'}
462 $r->get('/:mymessage')->to('foo#bar', mymessage => 'hi');
463
464 One more interesting effect, a placeholder automatically becomes
465 optional if there is already a stash value of the same name present,
466 this works similar to the regular expression "([^/.]+)?".
467
468 # / -> {controller => 'foo', action => 'bar', mymessage => 'hi'}
469 $r->get('/:mymessage')->to('foo#bar', mymessage => 'hi');
470
471 # /test/123 -> {controller => 'foo', action => 'bar', mymessage => 'hi'}
472 # /test/bye/123 -> {controller => 'foo', action => 'bar', mymessage => 'bye'}
473 $r->get('/test/:mymessage/123')->to('foo#bar', mymessage => 'hi');
474
475 And if two optional placeholders are only separated by a slash, that
476 slash can become optional as well.
477
478 # / -> {controller => 'foo', action => 'bar'}
479 # /users -> {controller => 'users', action => 'bar'}
480 # /users/list -> {controller => 'users', action => 'list'}
481 $r->get('/:controller/:action')->to('foo#bar');
482
483 Special stash values like "controller" and "action" can also be
484 placeholders, which is very convenient especially during development,
485 but should only be used very carefully, because every controller method
486 becomes a potential route. All uppercase methods as well as those
487 starting with an underscore are automatically hidden from the router
488 and you can use "hide" in Mojolicious::Routes to add additional ones.
489
490 # Hide "create" method in all controllers
491 $r->hide('create');
492
493 This has already been done for all attributes and methods from
494 Mojolicious::Controller.
495
496 Restrictive placeholders
497 A very easy way to make placeholders more restrictive are alternatives,
498 you just make a list of possible values, which then work similar to the
499 regular expression "(bender|leela)".
500
501 # /fry -> undef
502 # /bender -> {controller => 'foo', action => 'bar', name => 'bender'}
503 # /leela -> {controller => 'foo', action => 'bar', name => 'leela'}
504 $r->get('/:name' => [name => ['bender', 'leela']])->to('foo#bar');
505
506 You can also adjust the regular expressions behind placeholders
507 directly, just make sure not to use "^" and "$" or capturing groups
508 "(...)", because placeholders become part of a larger regular
509 expression internally, non-capturing groups "(?:...)" are fine though.
510
511 # /23 -> {controller => 'foo', action => 'bar', number => 23}
512 # /test -> undef
513 $r->get('/:number' => [number => qr/\d+/])->to('foo#bar');
514
515 # /23 -> undef
516 # /test -> {controller => 'foo', action => 'bar', name => 'test'}
517 $r->get('/:name' => [name => qr/[a-zA-Z]+/])->to('foo#bar');
518
519 This way you get easily readable routes and the raw power of regular
520 expressions.
521
522 Placeholder types
523 And if you have multiple routes using restrictive placeholders you can
524 also turn them into placeholder types with "add_type" in
525 Mojolicious::Routes.
526
527 # A type with alternatives
528 $r->add_type(futurama_name => ['bender', 'leela']);
529
530 # /fry -> undef
531 # /bender -> {controller => 'foo', action => 'bar', name => 'bender'}
532 # /leela -> {controller => 'foo', action => 'bar', name => 'leela'}
533 $r->get('/<name:futurama_name>')->to('foo#bar');
534
535 Placeholder types work just like restrictive placeholders, they are
536 just reusable with the "<placeholder:type>" notation.
537
538 # A type adjusting the regular expression
539 $r->add_type(upper => qr/[A-Z]+/);
540
541 # /user/ROOT -> {controller => 'users', action => 'show', name => 'ROOT'}
542 # /user/root -> undef
543 # /user/23 -> undef
544 $r->get('/user/<name:upper>')->to('users#show');
545
546 Some types like "num" are used so commonly that they are available by
547 default.
548
549 # /article/12 -> {controller => 'article', action => 'show', id => 12}
550 # /article/test -> undef
551 $r->get('/article/<id:num>')->to('articles#show');
552
553 For a full list of available placeholder types see also "TYPES" in
554 Mojolicious::Routes.
555
556 Introspection
557 The command Mojolicious::Command::routes can be used from the command
558 line to list all available routes together with names and underlying
559 regular expressions.
560
561 $ ./myapp.pl routes -v
562 /foo/:name .... POST fooname ^/foo/([^/.]+)/?(?:\.([^/]+))?$
563 /bar ..U. * bar ^/bar
564 +/baz ...W GET baz ^/baz/?(?:\.([^/]+))?$
565 /yada .... * yada ^/yada/?(?:\.([^/]+))?$
566
567 Under
568 To share code with multiple nested routes you can use "under" in
569 Mojolicious::Routes::Route, because unlike normal nested routes, the
570 routes generated with it have their own intermediate destination and
571 result in additional dispatch cycles when they match.
572
573 # /foo -> undef
574 # /foo/bar -> {controller => 'foo', action => 'baz'}
575 # {controller => 'foo', action => 'bar'}
576 my $foo = $r->under('/foo')->to('foo#baz');
577 $foo->get('/bar')->to('#bar');
578
579 The actual action code for this destination needs to return a true
580 value or the dispatch chain will be broken, this can be a very powerful
581 tool for authentication.
582
583 # /blackjack -> {cb => sub {...}}
584 # {controller => 'hideout', action => 'blackjack'}
585 my $auth = $r->under('/' => sub {
586 my $c = shift;
587
588 # Authenticated
589 return 1 if $c->req->headers->header('X-Bender');
590
591 # Not authenticated
592 $c->render(text => "You're not Bender.", status => 401);
593 return undef;
594 });
595 $auth->get('/blackjack')->to('hideout#blackjack');
596
597 Broken dispatch chains can be continued by calling "continue" in
598 Mojolicious::Controller, this allows for example, non-blocking
599 operations to finish before reaching the next dispatch cycle.
600
601 my $maybe = $r->under('/maybe' => sub {
602 my $c = shift;
603
604 # Wait 3 seconds and then give visitors a 50% chance to continue
605 Mojo::IOLoop->timer(3 => sub {
606
607 # Loser
608 return $c->render(text => 'No luck.') unless int rand 2;
609
610 # Winner
611 $c->continue;
612 });
613
614 return undef;
615 });
616 $maybe->get('/')->to('maybe#winner');
617
618 Every destination is just a snapshot of the stash at the time the route
619 matched, and only the "format" value is shared by all of them. For a
620 little more power you can introspect the preceding and succeeding
621 destinations with "match" in Mojolicious::Controller.
622
623 # Action of the fourth dispatch cycle
624 my $action = $c->match->stack->[3]{action};
625
626 Formats
627 File extensions like ".html" and ".txt" at the end of a route are
628 automatically detected and stored in the stash value "format".
629
630 # /foo -> {controller => 'foo', action => 'bar'}
631 # /foo.html -> {controller => 'foo', action => 'bar', format => 'html'}
632 # /foo.txt -> {controller => 'foo', action => 'bar', format => 'txt'}
633 $r->get('/foo')->to('foo#bar');
634
635 This for example, allows multiple templates in different formats to
636 share the same action code. Restrictive placeholders can also be used
637 to limit the allowed formats.
638
639 # /foo.txt -> undef
640 # /foo.rss -> {controller => 'foo', action => 'bar', format => 'rss'}
641 # /foo.xml -> {controller => 'foo', action => 'bar', format => 'xml'}
642 $r->get('/foo' => [format => ['rss', 'xml']])->to('foo#bar');
643
644 A "format" value can also be passed to "url_for" in
645 Mojolicious::Controller.
646
647 # /foo/bar.txt -> {controller => 'foo', action => 'bar', format => 'txt'}
648 $r->get('/foo/:action')->to('foo#')->name('baz');
649
650 # Generate URL "/foo/bar.txt" for route "baz"
651 my $url = $c->url_for('baz', action => 'bar', format => 'txt');
652
653 Or you can just disable format detection with a special type of
654 restrictive placeholder, which gets inherited by nested routes, and
655 then re-enable it on demand.
656
657 # /foo -> {controller => 'foo', action => 'bar'}
658 # /foo.html -> undef
659 $r->get('/foo' => [format => 0])->to('foo#bar');
660
661 # /foo -> {controller => 'foo', action => 'bar'}
662 # /foo.html -> undef
663 # /baz -> undef
664 # /baz.txt -> {controller => 'baz', action => 'yada', format => 'txt'}
665 # /baz.html -> {controller => 'baz', action => 'yada', format => 'html'}
666 # /baz.xml -> undef
667 my $inactive = $r->under([format => 0]);
668 $inactive->get('/foo')->to('foo#bar');
669 $inactive->get('/baz' => [format => ['txt', 'html']])->to('baz#yada');
670
671 WebSockets
672 With the method "websocket" in Mojolicious::Routes::Route you can
673 restrict access to WebSocket handshakes, which are normal "GET"
674 requests with some additional information.
675
676 # /echo (WebSocket handshake)
677 $r->websocket('/echo')->to('foo#echo');
678
679 # Controller
680 package MyApp::Controller::Foo;
681 use Mojo::Base 'Mojolicious::Controller';
682
683 # Action
684 sub echo {
685 my $self = shift;
686 $self->on(message => sub {
687 my ($self, $msg) = @_;
688 $self->send("echo: $msg");
689 });
690 }
691
692 1;
693
694 The connection gets established when you respond to the WebSocket
695 handshake request with a 101 response status, which happens
696 automatically if you subscribe to an event with "on" in
697 Mojolicious::Controller or send a message with "send" in
698 Mojolicious::Controller right away.
699
700 GET /echo HTTP/1.1
701 Host: mojolicious.org
702 User-Agent: Mojolicious (Perl)
703 Connection: Upgrade
704 Upgrade: websocket
705 Sec-WebSocket-Key: IDM3ODE4NDk2MjA1OTcxOQ==
706 Sec-WebSocket-Version: 13
707
708 HTTP/1.1 101 Switching Protocols
709 Server: Mojolicious (Perl)
710 Date: Tue, 03 Feb 2015 17:08:24 GMT
711 Connection: Upgrade
712 Upgrade: websocket
713 Sec-WebSocket-Accept: SWsp5N2iNxPbHlcOTIw8ERvyVPY=
714
715 Catch-all route
716 Since routes match in the order in which they were defined, you can
717 catch all requests that did not match in your last route with an
718 optional wildcard placeholder.
719
720 # * /*
721 $r->any('/*whatever' => {whatever => ''} => sub {
722 my $c = shift;
723 my $whatever = $c->param('whatever');
724 $c->render(text => "/$whatever did not match.", status => 404);
725 });
726
727 Conditions
728 Conditions such as "headers", "agent" and "host" from
729 Mojolicious::Plugin::HeaderCondition can be applied to any route with
730 the method "over" in Mojolicious::Routes::Route, and allow even more
731 powerful route constructs.
732
733 # / (Origin: http://perl.org)
734 $r->get('/')->over(headers => {Origin => qr/perl\.org/})->to('foo#bar');
735
736 # / (Firefox)
737 $r->get('/')->over(agent => qr/Firefox/)->to('browser-test#firefox');
738
739 # / (Internet Explorer)
740 $r->get('/')->over(agent => qr/Internet Explorer/)->to('browser-test#ie');
741
742 # http://mojolicious.org/perldoc
743 $r->get('/perldoc')->over(host => 'mojolicious.org')->to('perldoc#index');
744
745 Just be aware that conditions are too complex for the routing cache,
746 which normally speeds up recurring requests, and can therefore reduce
747 performance.
748
749 Hooks
750 Hooks operate outside the routing system and allow you to extend the
751 framework itself by sharing code with all requests indiscriminately
752 through "hook" in Mojolicious, which makes them a very powerful tool
753 especially for plugins.
754
755 # Application
756 package MyApp;
757 use Mojo::Base 'Mojolicious';
758
759 sub startup {
760 my $self = shift;
761
762 # Check all requests for a "/test" prefix
763 $self->hook(before_dispatch => sub {
764 my $c = shift;
765 $c->render(text => 'This request did not reach the router.')
766 if $c->req->url->path->contains('/test');
767 });
768
769 # These will not be reached if the hook above renders a response
770 my $r = $self->routes;
771 $r->get('/welcome')->to('foo#welcome');
772 $r->post('/bye')->to('foo#bye');
773 }
774
775 1;
776
777 Post-processing the response to add or remove headers is a very common
778 use.
779
780 # Make sure static files are cached
781 $app->hook(after_static => sub {
782 my $c = shift;
783 $c->res->headers->cache_control('max-age=3600, must-revalidate');
784 });
785
786 # Remove a default header
787 $app->hook(after_dispatch => sub {
788 my $c = shift;
789 $c->res->headers->remove('Server');
790 });
791
792 Same for pre-processing the request.
793
794 # Choose template variant based on request headers
795 $app->hook(before_dispatch => sub {
796 my $c = shift;
797 return unless my $agent = $c->req->headers->user_agent;
798 $c->stash(variant => 'ie') if $agent =~ /Internet Explorer/;
799 });
800
801 Or more advanced extensions to add monitoring to your application.
802
803 # Forward exceptions to a web service
804 $app->hook(after_dispatch => sub {
805 my $c = shift;
806 return unless my $e = $c->stash('exception');
807 $c->ua->post('https://example.com/bugs' => form => {exception => $e});
808 });
809
810 You can even extend much of the core functionality.
811
812 # Make controller object available to actions as $_
813 $app->hook(around_action => sub {
814 my ($next, $c, $action, $last) = @_;
815 local $_ = $c;
816 return $next->();
817 });
818
819 # Pass route name as argument to actions
820 $app->hook(around_action => sub {
821 my ($next, $c, $action, $last) = @_;
822 return $c->$action($c->current_route);
823 });
824
825 For a full list of available hooks see "HOOKS" in Mojolicious.
826
828 Less commonly used and more powerful features.
829
830 Shortcuts
831 To make route generation more expressive, you can also add your own
832 shortcuts with "add_shortcut" in Mojolicious::Routes.
833
834 # Simple "resource" shortcut
835 $r->add_shortcut(resource => sub {
836 my ($r, $name) = @_;
837
838 # Prefix for resource
839 my $resource = $r->any("/$name")->to("$name#");
840
841 # Render a list of resources
842 $resource->get('/')->to('#index')->name($name);
843
844 # Render a form to create a new resource (submitted to "store")
845 $resource->get('/create')->to('#create')->name("create_$name");
846
847 # Store newly created resource (submitted by "create")
848 $resource->post->to('#store')->name("store_$name");
849
850 # Render a specific resource
851 $resource->get('/:id')->to('#show')->name("show_$name");
852
853 # Render a form to edit a resource (submitted to "update")
854 $resource->get('/:id/edit')->to('#edit')->name("edit_$name");
855
856 # Store updated resource (submitted by "edit")
857 $resource->put('/:id')->to('#update')->name("update_$name");
858
859 # Remove a resource
860 $resource->delete('/:id')->to('#remove')->name("remove_$name");
861
862 return $resource;
863 });
864
865 # GET /users -> {controller => 'users', action => 'index'}
866 # GET /users/create -> {controller => 'users', action => 'create'}
867 # POST /users -> {controller => 'users', action => 'store'}
868 # GET /users/23 -> {controller => 'users', action => 'show', id => 23}
869 # GET /users/23/edit -> {controller => 'users', action => 'edit', id => 23}
870 # PUT /users/23 -> {controller => 'users', action => 'update', id => 23}
871 # DELETE /users/23 -> {controller => 'users', action => 'remove', id => 23}
872 $r->resource('users');
873
874 Rearranging routes
875 From application startup until the first request has arrived, all
876 routes can still be moved around or even removed with methods like
877 "add_child" in Mojolicious::Routes::Route and "remove" in
878 Mojolicious::Routes::Route.
879
880 # GET /example/show -> {controller => 'example', action => 'show'}
881 my $show = $r->get('/show')->to('example#show');
882 $r->any('/example')->add_child($show);
883
884 # Nothing
885 $r->get('/secrets/show')->to('secrets#show')->name('show_secrets');
886 $r->find('show_secrets')->remove;
887
888 Especially for rearranging routes created by plugins this can be very
889 useful, to find routes by their name you can use "find" in
890 Mojolicious::Routes::Route.
891
892 # GET /example/test -> {controller => 'example', action => 'test'}
893 $r->get('/something/else')->to('something#else')->name('test');
894 my $test = $r->find('test');
895 $test->pattern->parse('/example/test');
896 $test->pattern->defaults({controller => 'example', action => 'test'});
897
898 Even the route pattern and destination can still be changed with
899 "parse" in Mojolicious::Routes::Pattern and "defaults" in
900 Mojolicious::Routes::Pattern.
901
902 Adding conditions
903 You can also add your own conditions with the method "add_condition" in
904 Mojolicious::Routes. All conditions are basically router plugins that
905 run every time a new request arrives, and which need to return a true
906 value for the route to match.
907
908 # A condition that randomly allows a route to match
909 $r->add_condition(random => sub {
910 my ($route, $c, $captures, $num) = @_;
911
912 # Loser
913 return undef if int rand $num;
914
915 # Winner
916 return 1;
917 });
918
919 # /maybe (25% chance)
920 $r->get('/maybe')->over(random => 4)->to('foo#bar');
921
922 Use whatever request information you need.
923
924 # A condition to check query parameters (useful for mock web services)
925 $r->add_condition(query => sub {
926 my ($route, $c, $captures, $hash) = @_;
927
928 for my $key (keys %$hash) {
929 my $param = $c->req->url->query->param($key);
930 return undef unless defined $param && $param eq $hash->{$key};
931 }
932
933 return 1;
934 });
935
936 # /hello?to=world&test=1
937 $r->get('/hello')->over(query => {test => 1, to => 'world'})->to('foo#bar');
938
939 Condition plugins
940 You can also package your conditions as reusable plugins.
941
942 # Plugin
943 package Mojolicious::Plugin::WerewolfCondition;
944 use Mojo::Base 'Mojolicious::Plugin';
945
946 use Astro::MoonPhase;
947
948 sub register {
949 my ($self, $app) = @_;
950
951 # Add "werewolf" condition
952 $app->routes->add_condition(werewolf => sub {
953 my ($route, $c, $captures, $days) = @_;
954
955 # Keep the werewolves out!
956 return undef if abs(14 - (phase(time))[2]) > ($days / 2);
957
958 # It's ok, no werewolf
959 return 1;
960 });
961 }
962
963 1;
964
965 Now just load the plugin and you are ready to use the condition in all
966 your applications.
967
968 # Application
969 package MyApp;
970 use Mojo::Base 'Mojolicious';
971
972 sub startup {
973 my $self = shift;
974
975 # Plugin
976 $self->plugin('WerewolfCondition');
977
978 # /hideout (keep them out for 4 days after full moon)
979 $self->routes->get('/hideout')->over(werewolf => 4)
980 ->to(controller => 'foo', action => 'bar');
981 }
982
983 1;
984
985 Mount applications
986 The easiest way to embed one application into another is
987 Mojolicious::Plugin::Mount, which allows you to mount whole self-
988 contained applications under a domain and/or prefix.
989
990 use Mojolicious::Lite;
991
992 # Whole application mounted under "/prefix"
993 plugin Mount => {'/prefix' => '/home/sri/myapp/script/myapp'};
994
995 # Mount application with subdomain
996 plugin Mount => {'test.example.com' => '/home/sri/myapp2.pl'};
997
998 # Normal route
999 get '/' => sub { shift->render(text => 'Hello World!') };
1000
1001 app->start;
1002
1003 Embed applications
1004 For a little more power you can also embed applications by using them
1005 instead of a controller. This allows for example, the use of the
1006 Mojolicious::Lite domain specific language in normal Mojolicious
1007 controllers.
1008
1009 # Controller
1010 package MyApp::Controller::Bar;
1011 use Mojolicious::Lite;
1012
1013 # /hello
1014 get '/hello' => sub {
1015 my $c = shift;
1016 my $name = $c->param('name');
1017 $c->render(text => "Hello $name.");
1018 };
1019
1020 1;
1021
1022 With the method "detour" in Mojolicious::Routes::Route which is very
1023 similar to "to" in Mojolicious::Routes::Route, you can allow the route
1024 to partially match and use only the remaining path in the embedded
1025 application, the base path will be passed along in the "path" stash
1026 value.
1027
1028 # /foo/*
1029 $r->any('/foo')->detour('bar#', name => 'Mojo');
1030
1031 A minimal embeddable application is nothing more than a subclass of
1032 Mojolicious, containing a "handler" method accepting
1033 Mojolicious::Controller objects.
1034
1035 package MyApp::Controller::Bar;
1036 use Mojo::Base 'Mojolicious';
1037
1038 sub handler {
1039 my ($self, $c) = @_;
1040 $c->res->code(200);
1041 my $name = $c->param('name');
1042 $c->res->body("Hello $name.");
1043 }
1044
1045 1;
1046
1047 The host application will only share very little information with the
1048 embedded application through the stash. So you cannot currently use
1049 route placeholders in routes leading to embedded applications, since
1050 that would cause problems with "url_for" in Mojolicious::Controller.
1051
1052 Application plugins
1053 You can even package applications as self-contained reusable plugins.
1054
1055 # Plugin
1056 package Mojolicious::Plugin::MyEmbeddedApp;
1057 use Mojo::Base 'Mojolicious::Plugin';
1058
1059 sub register {
1060 my ($self, $app) = @_;
1061
1062 # Automatically add route
1063 $app->routes->any('/foo')->detour(app => EmbeddedApp::app());
1064 }
1065
1066 package EmbeddedApp;
1067 use Mojolicious::Lite;
1068
1069 get '/bar' => 'bar';
1070
1071 1;
1072 __DATA__
1073 @@ bar.html.ep
1074 Hello World!
1075
1076 The "app" stash value, which won't be inherited by nested routes, can
1077 be used for already instantiated applications. Now just load the
1078 plugin and you're done.
1079
1080 # Application
1081 package MyApp;
1082 use Mojo::Base 'Mojolicious';
1083
1084 sub startup {
1085 my $self = shift;
1086
1087 # Plugin
1088 $self->plugin('MyEmbeddedApp');
1089 }
1090
1091 1;
1092
1094 You can continue with Mojolicious::Guides now or take a look at the
1095 Mojolicious wiki <http://github.com/mojolicious/mojo/wiki>, which
1096 contains a lot more documentation and examples by many different
1097 authors.
1098
1100 If you have any questions the documentation might not yet answer, don't
1101 hesitate to ask on the mailing list
1102 <http://groups.google.com/group/mojolicious> or the official IRC
1103 channel "#mojo" on "irc.freenode.net" (chat now!
1104 <https://webchat.freenode.net/#mojo>).
1105
1106
1107
1108perl v5.32.0 2020-07-28 Mojolicious::Guides::Routing(3)