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