source: main/trunk/greenstone2/perllib/cpan/Mojolicious/Guides/Routing.pod@ 32205

Last change on this file since 32205 was 32205, checked in by ak19, 6 years ago

First set of commits to do with implementing the new 'paged_html' output option of PDFPlugin that uses using xpdftools' new pdftohtml. So far tested only on Linux (64 bit), but things work there so I'm optimistically committing the changes since they work. 2. Committing the pre-built Linux binaries of XPDFtools for both 32 and 64 bit built by the XPDF group. 2. To use the correct bitness variant of xpdftools, setup.bash now exports the BITNESS env var, consulted by gsConvert.pl. 3. All the perl code changes to do with using xpdf tools' pdftohtml to generate paged_html and feed it in the desired form into GS(3): gsConvert.pl, PDFPlugin.pm and its parent ConvertBinaryPFile.pm have been modified to make it all work. xpdftools' pdftohtml generates a folder containing an html file and a screenshot for each page in a PDF (as well as an index.html linking to each page's html). However, we want a single html file that contains each individual 'page' html's content in a div, and need to do some further HTML style, attribute and structure modifications to massage the xpdftool output to what we want for GS. In order to parse and manipulate the HTML 'DOM' to do this, we're using the Mojo::DOM package that Dr Bainbridge found and which he's compiled up. Mojo::DOM is therefore also committed in this revision. Some further changes and some display fixes are required, but need to check with the others about that.

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