add files
|
1 |
package Mojolicious; |
2 |
use Mojo::Base 'Mojo'; |
|
3 | ||
4 |
# "Fry: Shut up and take my money!" |
|
5 |
use Carp 'croak'; |
|
6 |
use Mojo::Exception; |
|
7 |
use Mojo::Util qw(decamelize deprecated); |
|
8 |
use Mojolicious::Commands; |
|
9 |
use Mojolicious::Controller; |
|
10 |
use Mojolicious::Plugins; |
|
11 |
use Mojolicious::Renderer; |
|
12 |
use Mojolicious::Routes; |
|
13 |
use Mojolicious::Sessions; |
|
14 |
use Mojolicious::Static; |
|
15 |
use Mojolicious::Types; |
|
16 |
use Mojolicious::Validator; |
|
17 |
use Scalar::Util qw(blessed weaken); |
|
18 |
use Time::HiRes 'gettimeofday'; |
|
19 | ||
20 |
has commands => sub { |
|
21 |
my $commands = Mojolicious::Commands->new(app => shift); |
|
22 |
weaken $commands->{app}; |
|
23 |
return $commands; |
|
24 |
}; |
|
25 |
has controller_class => 'Mojolicious::Controller'; |
|
26 |
has mode => sub { $ENV{MOJO_MODE} || $ENV{PLACK_ENV} || 'development' }; |
|
27 |
has moniker => sub { decamelize ref shift }; |
|
28 |
has plugins => sub { Mojolicious::Plugins->new }; |
|
29 |
has renderer => sub { Mojolicious::Renderer->new }; |
|
30 |
has routes => sub { Mojolicious::Routes->new }; |
|
31 |
has secret => sub { |
|
32 |
my $self = shift; |
|
33 | ||
34 |
# Warn developers about insecure default |
|
35 |
$self->log->debug('Your secret passphrase needs to be changed!!!'); |
|
36 | ||
37 |
# Default to moniker |
|
38 |
return $self->moniker; |
|
39 |
}; |
|
40 |
has sessions => sub { Mojolicious::Sessions->new }; |
|
41 |
has static => sub { Mojolicious::Static->new }; |
|
42 |
has types => sub { Mojolicious::Types->new }; |
|
43 |
has validator => sub { Mojolicious::Validator->new }; |
|
44 | ||
45 |
our $CODENAME = 'Top Hat'; |
|
46 |
our $VERSION = '4.57'; |
|
47 | ||
48 |
sub AUTOLOAD { |
|
49 |
my $self = shift; |
|
50 | ||
51 |
my ($package, $method) = our $AUTOLOAD =~ /^([\w:]+)::(\w+)$/; |
|
52 |
croak "Undefined subroutine &${package}::$method called" |
|
53 |
unless blessed $self && $self->isa(__PACKAGE__); |
|
54 | ||
55 |
# Call helper with fresh controller |
|
56 |
croak qq{Can't locate object method "$method" via package "$package"} |
|
57 |
unless my $helper = $self->renderer->helpers->{$method}; |
|
58 |
return $self->controller_class->new(app => $self)->$helper(@_); |
|
59 |
} |
|
60 | ||
61 |
sub DESTROY { } |
|
62 | ||
63 |
sub new { |
|
64 |
my $self = shift->SUPER::new(@_); |
|
65 | ||
66 |
my $home = $self->home; |
|
67 |
push @{$self->renderer->paths}, $home->rel_dir('templates'); |
|
68 |
push @{$self->static->paths}, $home->rel_dir('public'); |
|
69 | ||
70 |
# Default to application namespace |
|
71 |
my $r = $self->routes->namespaces([ref $self]); |
|
72 | ||
73 |
# Hide controller attributes/methods and "handler" |
|
74 |
$r->hide(qw(app continue cookie finish flash handler match on param)); |
|
75 |
$r->hide(qw(redirect_to render render_exception render_later render_maybe)); |
|
76 |
$r->hide(qw(render_not_found render_static rendered req res respond_to)); |
|
77 |
$r->hide(qw(send session signed_cookie stash tx url_for validation write)); |
|
78 |
$r->hide(qw(write_chunk)); |
|
79 | ||
80 |
# Check if we have a log directory |
|
81 |
my $mode = $self->mode; |
|
82 |
$self->log->path($home->rel_file("log/$mode.log")) |
|
83 |
if -w $home->rel_file('log'); |
|
84 | ||
85 |
$self->plugin($_) |
|
86 |
for qw(HeaderCondition DefaultHelpers TagHelpers EPLRenderer EPRenderer); |
|
87 | ||
88 |
# Exception handling should be first in chain |
|
89 |
$self->hook(around_dispatch => \&_exception); |
|
90 | ||
91 |
# Reduced log output outside of development mode |
|
92 |
$self->log->level('info') unless $mode eq 'development'; |
|
93 | ||
94 |
# DEPRECATED in Top Hat! |
|
95 |
if (my $sub = $self->can("${mode}_mode")) { |
|
96 |
deprecated qq{"sub ${mode}_mode {...}" in application class is DEPRECATED}; |
|
97 |
$self->$sub; |
|
98 |
} |
|
99 | ||
100 |
$self->startup; |
|
101 | ||
102 |
return $self; |
|
103 |
} |
|
104 | ||
105 |
sub build_tx { |
|
106 |
my $self = shift; |
|
107 |
my $tx = Mojo::Transaction::HTTP->new; |
|
108 |
$self->plugins->emit_hook(after_build_tx => $tx, $self); |
|
109 |
return $tx; |
|
110 |
} |
|
111 | ||
112 |
sub defaults { shift->_dict(defaults => @_) } |
|
113 | ||
114 |
sub dispatch { |
|
115 |
my ($self, $c) = @_; |
|
116 | ||
117 |
# Prepare transaction |
|
118 |
my $tx = $c->tx; |
|
119 |
$tx->res->code(undef) if $tx->is_websocket; |
|
120 |
$self->sessions->load($c); |
|
121 |
my $plugins = $self->plugins->emit_hook(before_dispatch => $c); |
|
122 | ||
123 |
# Try to find a static file |
|
124 |
$self->static->dispatch($c) and $plugins->emit_hook(after_static => $c) |
|
125 |
unless $tx->res->code; |
|
126 | ||
127 |
# Start timer (ignore static files) |
|
128 |
my $stash = $c->stash; |
|
129 |
unless ($stash->{'mojo.static'} || $stash->{'mojo.started'}) { |
|
130 |
my $req = $c->req; |
|
131 |
my $method = $req->method; |
|
132 |
my $path = $req->url->path->to_abs_string; |
|
133 |
$self->log->debug(qq{$method "$path".}); |
|
134 |
$stash->{'mojo.started'} = [gettimeofday]; |
|
135 |
} |
|
136 | ||
137 |
# Routes |
|
138 |
$plugins->emit_hook(before_routes => $c); |
|
139 |
my $res = $tx->res; |
|
140 |
return if $res->code; |
|
141 |
if (my $code = ($tx->req->error)[1]) { $res->code($code) } |
|
142 |
elsif ($tx->is_websocket) { $res->code(426) } |
|
143 |
$c->render_not_found unless $self->routes->dispatch($c) || $tx->res->code; |
|
144 |
} |
|
145 | ||
146 |
sub handler { |
|
147 |
my ($self, $tx) = @_; |
|
148 | ||
149 |
# Embedded application |
|
150 |
my $stash = {}; |
|
151 |
if (my $sub = $tx->can('stash')) { ($stash, $tx) = ($tx->$sub, $tx->tx) } |
|
152 |
$stash->{'mojo.secret'} //= $self->secret; |
|
153 | ||
154 |
# Build default controller |
|
155 |
my $defaults = $self->defaults; |
|
156 |
@{$stash}{keys %$defaults} = values %$defaults; |
|
157 |
my $c |
|
158 |
= $self->controller_class->new(app => $self, stash => $stash, tx => $tx); |
|
159 |
weaken $c->{$_} for qw(app tx); |
|
160 | ||
161 |
# Dispatcher has to be last in the chain |
|
162 |
++$self->{dispatch} |
|
163 |
and $self->hook(around_action => sub { $_[2]->($_[1]) }) |
|
164 |
and $self->hook(around_dispatch => sub { $_[1]->app->dispatch($_[1]) }) |
|
165 |
unless $self->{dispatch}; |
|
166 | ||
167 |
# Process with chain |
|
168 |
$self->plugins->emit_chain(around_dispatch => $c); |
|
169 | ||
170 |
# Delayed response |
|
171 |
$self->log->debug('Nothing has been rendered, expecting delayed response.') |
|
172 |
unless $tx->is_writing; |
|
173 |
} |
|
174 | ||
175 |
sub helper { |
|
176 |
my ($self, $name, $cb) = @_; |
|
177 |
my $r = $self->renderer; |
|
178 |
$self->log->debug(qq{Helper "$name" already exists, replacing.}) |
|
179 |
if exists $r->helpers->{$name}; |
|
180 |
$r->add_helper($name => $cb); |
|
181 |
} |
|
182 | ||
183 |
sub hook { shift->plugins->on(@_) } |
|
184 | ||
185 |
sub plugin { |
|
186 |
my $self = shift; |
|
187 |
$self->plugins->register_plugin(shift, $self, @_); |
|
188 |
} |
|
189 | ||
190 |
sub start { shift->commands->run(@_ ? @_ : @ARGV) } |
|
191 | ||
192 |
sub startup { } |
|
193 | ||
194 |
sub _exception { |
|
195 |
my ($next, $c) = @_; |
|
196 |
local $SIG{__DIE__} |
|
197 |
= sub { ref $_[0] ? CORE::die($_[0]) : Mojo::Exception->throw(@_) }; |
|
198 |
$c->render_exception($@) unless eval { $next->(); 1 }; |
|
199 |
} |
|
200 | ||
201 |
1; |
|
202 | ||
203 |
=encoding utf8 |
|
204 | ||
205 |
=head1 NAME |
|
206 | ||
207 |
Mojolicious - Real-time web framework |
|
208 | ||
209 |
=head1 SYNOPSIS |
|
210 | ||
211 |
# Application |
|
212 |
package MyApp; |
|
213 |
use Mojo::Base 'Mojolicious'; |
|
214 | ||
215 |
# Route |
|
216 |
sub startup { |
|
217 |
my $self = shift; |
|
218 |
$self->routes->get('/hello')->to('foo#hello'); |
|
219 |
} |
|
220 | ||
221 |
# Controller |
|
222 |
package MyApp::Foo; |
|
223 |
use Mojo::Base 'Mojolicious::Controller'; |
|
224 | ||
225 |
# Action |
|
226 |
sub hello { |
|
227 |
my $self = shift; |
|
228 |
$self->render(text => 'Hello World!'); |
|
229 |
} |
|
230 | ||
231 |
=head1 DESCRIPTION |
|
232 | ||
233 |
Take a look at our excellent documentation in L<Mojolicious::Guides>! |
|
234 | ||
235 |
=head1 HOOKS |
|
236 | ||
237 |
L<Mojolicious> will emit the following hooks in the listed order. |
|
238 | ||
239 |
=head2 after_build_tx |
|
240 | ||
241 |
Emitted right after the transaction is built and before the HTTP request gets |
|
242 |
parsed. |
|
243 | ||
244 |
$app->hook(after_build_tx => sub { |
|
245 |
my ($tx, $app) = @_; |
|
246 |
... |
|
247 |
}); |
|
248 | ||
249 |
This is a very powerful hook and should not be used lightly, it makes some |
|
250 |
rather advanced features such as upload progress bars possible. Note that this |
|
251 |
hook will not work for embedded applications. (Passed the transaction and |
|
252 |
application object) |
|
253 | ||
254 |
=head2 before_dispatch |
|
255 | ||
256 |
Emitted right before the static file server and router start their work. |
|
257 | ||
258 |
$app->hook(before_dispatch => sub { |
|
259 |
my $c = shift; |
|
260 |
... |
|
261 |
}); |
|
262 | ||
263 |
Very useful for rewriting incoming requests and other preprocessing tasks. |
|
264 |
(Passed the default controller object) |
|
265 | ||
266 |
=head2 after_static |
|
267 | ||
268 |
Emitted after a static file response has been generated by the static file |
|
269 |
server. |
|
270 | ||
271 |
$app->hook(after_static => sub { |
|
272 |
my $c = shift; |
|
273 |
... |
|
274 |
}); |
|
275 | ||
276 |
Mostly used for post-processing static file responses. (Passed the default |
|
277 |
controller object) |
|
278 | ||
279 |
=head2 before_routes |
|
280 | ||
281 |
Emitted after the static file server determined if a static file should be |
|
282 |
served and before the router starts its work. |
|
283 | ||
284 |
$app->hook(before_routes => sub { |
|
285 |
my $c = shift; |
|
286 |
... |
|
287 |
}); |
|
288 | ||
289 |
Mostly used for custom dispatchers and collecting metrics. (Passed the default |
|
290 |
controller object) |
|
291 | ||
292 |
=head2 around_action |
|
293 | ||
294 |
Emitted right before an action gets invoked and wraps around it, so you have |
|
295 |
to manually forward to the next hook if you want to continue the chain. |
|
296 |
Default action dispatching is the last hook in the chain, yours will run |
|
297 |
before it. |
|
298 | ||
299 |
$app->hook(around_action => sub { |
|
300 |
my ($next, $c, $action, $last) = @_; |
|
301 |
... |
|
302 |
return $next->(); |
|
303 |
}); |
|
304 | ||
305 |
This is a very powerful hook and should not be used lightly, it allows you for |
|
306 |
example to pass additional arguments to actions or handle return values |
|
307 |
differently. (Passed a callback leading to the next hook, the current |
|
308 |
controller object, the action callback and a flag indicating if this action is |
|
309 |
an endpoint) |
|
310 | ||
311 |
=head2 after_render |
|
312 | ||
313 |
Emitted after content has been generated by the renderer that is not partial. |
|
314 |
Note that this hook can trigger out of order due to its dynamic nature, and |
|
315 |
with embedded applications will only work for the application that is |
|
316 |
rendering. |
|
317 | ||
318 |
$app->hook(after_render => sub { |
|
319 |
my ($c, $output, $format) = @_; |
|
320 |
... |
|
321 |
}); |
|
322 | ||
323 |
Mostly used for post-processing dynamically generated content. (Passed the |
|
324 |
current controller object, a reference to the content and the format) |
|
325 | ||
326 |
=head2 after_dispatch |
|
327 | ||
328 |
Emitted in reverse order after a response has been rendered. Note that this |
|
329 |
hook can trigger out of order due to its dynamic nature, and with embedded |
|
330 |
applications will only work for the application that is rendering. |
|
331 | ||
332 |
$app->hook(after_dispatch => sub { |
|
333 |
my $c = shift; |
|
334 |
... |
|
335 |
}); |
|
336 | ||
337 |
Useful for rewriting outgoing responses and other post-processing tasks. |
|
338 |
(Passed the current controller object) |
|
339 | ||
340 |
=head2 around_dispatch |
|
341 | ||
342 |
Emitted right before the L</"before_dispatch"> hook and wraps around the whole |
|
343 |
dispatch process, so you have to manually forward to the next hook if you want |
|
344 |
to continue the chain. Default exception handling with |
|
345 |
L<Mojolicious::Controller/"render_exception"> is the first hook in the chain |
|
346 |
and a call to L</"dispatch"> the last, yours will be in between. |
|
347 | ||
348 |
$app->hook(around_dispatch => sub { |
|
349 |
my ($next, $c) = @_; |
|
350 |
... |
|
351 |
$next->(); |
|
352 |
... |
|
353 |
}); |
|
354 | ||
355 |
This is a very powerful hook and should not be used lightly, it allows you for |
|
356 |
example to customize application wide exception handling, consider it the |
|
357 |
sledgehammer in your toolbox. (Passed a callback leading to the next hook and |
|
358 |
the default controller object) |
|
359 | ||
360 |
=head1 ATTRIBUTES |
|
361 | ||
362 |
L<Mojolicious> inherits all attributes from L<Mojo> and implements the |
|
363 |
following new ones. |
|
364 | ||
365 |
=head2 commands |
|
366 | ||
367 |
my $commands = $app->commands; |
|
368 |
$app = $app->commands(Mojolicious::Commands->new); |
|
369 | ||
370 |
Command line interface for your application, defaults to a |
|
371 |
L<Mojolicious::Commands> object. |
|
372 | ||
373 |
# Add another namespace to load commands from |
|
374 |
push @{$app->commands->namespaces}, 'MyApp::Command'; |
|
375 | ||
376 |
=head2 controller_class |
|
377 | ||
378 |
my $class = $app->controller_class; |
|
379 |
$app = $app->controller_class('Mojolicious::Controller'); |
|
380 | ||
381 |
Class to be used for the default controller, defaults to |
|
382 |
L<Mojolicious::Controller>. |
|
383 | ||
384 |
=head2 mode |
|
385 | ||
386 |
my $mode = $app->mode; |
|
387 |
$app = $app->mode('production'); |
|
388 | ||
389 |
The operating mode for your application, defaults to a value from the |
|
390 |
MOJO_MODE and PLACK_ENV environment variables or C<development>. Right before |
|
391 |
calling L</"startup">, L<Mojolicious> will pick up the current mode, name the |
|
392 |
log file after it and raise the log level from C<debug> to C<info> if it has a |
|
393 |
value other than C<development>. |
|
394 | ||
395 |
=head2 moniker |
|
396 | ||
397 |
my $moniker = $app->moniker; |
|
398 |
$app = $app->moniker('foo_bar'); |
|
399 | ||
400 |
Moniker of this application, often used as default filename for configuration |
|
401 |
files and the like, defaults to decamelizing the application class with |
|
402 |
L<Mojo::Util/"decamelize">. |
|
403 | ||
404 |
=head2 plugins |
|
405 | ||
406 |
my $plugins = $app->plugins; |
|
407 |
$app = $app->plugins(Mojolicious::Plugins->new); |
|
408 | ||
409 |
The plugin manager, defaults to a L<Mojolicious::Plugins> object. See the |
|
410 |
L</"plugin"> method below if you want to load a plugin. |
|
411 | ||
412 |
# Add another namespace to load plugins from |
|
413 |
push @{$app->plugins->namespaces}, 'MyApp::Plugin'; |
|
414 | ||
415 |
=head2 renderer |
|
416 | ||
417 |
my $renderer = $app->renderer; |
|
418 |
$app = $app->renderer(Mojolicious::Renderer->new); |
|
419 | ||
420 |
Used in your application to render content, defaults to a |
|
421 |
L<Mojolicious::Renderer> object. The two main renderer plugins |
|
422 |
L<Mojolicious::Plugin::EPRenderer> and L<Mojolicious::Plugin::EPLRenderer> |
|
423 |
contain more information. |
|
424 | ||
425 |
# Add another "templates" directory |
|
426 |
push @{$app->renderer->paths}, '/home/sri/templates'; |
|
427 | ||
428 |
# Add another class with templates in DATA section |
|
429 |
push @{$app->renderer->classes}, 'Mojolicious::Plugin::Fun'; |
|
430 | ||
431 |
=head2 routes |
|
432 | ||
433 |
my $routes = $app->routes; |
|
434 |
$app = $app->routes(Mojolicious::Routes->new); |
|
435 | ||
436 |
The router, defaults to a L<Mojolicious::Routes> object. You use this in your |
|
437 |
startup method to define the url endpoints for your application. |
|
438 | ||
439 |
# Add routes |
|
440 |
my $r = $app->routes; |
|
441 |
$r->get('/foo/bar')->to('test#foo', title => 'Hello Mojo!'); |
|
442 |
$r->post('/baz')->to('test#baz'); |
|
443 | ||
444 |
# Add another namespace to load controllers from |
|
445 |
push @{$app->routes->namespaces}, 'MyApp::Controller'; |
|
446 | ||
447 |
=head2 secret |
|
448 | ||
449 |
my $secret = $app->secret; |
|
450 |
$app = $app->secret('passw0rd'); |
|
451 | ||
452 |
A secret passphrase used for signed cookies and the like, defaults to the |
|
453 |
L</"moniker"> of this application, which is not very secure, so you should |
|
454 |
change it!!! As long as you are using the insecure default there will be debug |
|
455 |
messages in the log file reminding you to change your passphrase. |
|
456 | ||
457 |
=head2 sessions |
|
458 | ||
459 |
my $sessions = $app->sessions; |
|
460 |
$app = $app->sessions(Mojolicious::Sessions->new); |
|
461 | ||
462 |
Signed cookie based session manager, defaults to a L<Mojolicious::Sessions> |
|
463 |
object. You can usually leave this alone, see |
|
464 |
L<Mojolicious::Controller/"session"> for more information about working with |
|
465 |
session data. |
|
466 | ||
467 |
# Change name of cookie used for all sessions |
|
468 |
$app->sessions->cookie_name('mysession'); |
|
469 | ||
470 |
=head2 static |
|
471 | ||
472 |
my $static = $app->static; |
|
473 |
$app = $app->static(Mojolicious::Static->new); |
|
474 | ||
475 |
For serving static files from your C<public> directories, defaults to a |
|
476 |
L<Mojolicious::Static> object. |
|
477 | ||
478 |
# Add another "public" directory |
|
479 |
push @{$app->static->paths}, '/home/sri/public'; |
|
480 | ||
481 |
# Add another class with static files in DATA section |
|
482 |
push @{$app->static->classes}, 'Mojolicious::Plugin::Fun'; |
|
483 | ||
484 |
=head2 types |
|
485 | ||
486 |
my $types = $app->types; |
|
487 |
$app = $app->types(Mojolicious::Types->new); |
|
488 | ||
489 |
Responsible for connecting file extensions with MIME types, defaults to a |
|
490 |
L<Mojolicious::Types> object. |
|
491 | ||
492 |
# Add custom MIME type |
|
493 |
$app->types->type(twt => 'text/tweet'); |
|
494 | ||
495 |
=head2 validator |
|
496 | ||
497 |
my $validator = $app->validator; |
|
498 |
$app = $app->validator(Mojolicious::Validator->new); |
|
499 | ||
500 |
Validate form data, defaults to a L<Mojolicious::Validator> object. |
|
501 | ||
502 |
=head1 METHODS |
|
503 | ||
504 |
L<Mojolicious> inherits all methods from L<Mojo> and implements the following |
|
505 |
new ones. |
|
506 | ||
507 |
=head2 new |
|
508 | ||
509 |
my $app = Mojolicious->new; |
|
510 | ||
511 |
Construct a new L<Mojolicious> application, calling C<${mode}_mode> and |
|
512 |
L</"startup"> in the process. Will automatically detect your home directory |
|
513 |
and set up logging based on your current operating mode. Also sets up the |
|
514 |
renderer, static file server, a default set of plugins and an |
|
515 |
L</"around_dispatch"> hook with the default exception handling. |
|
516 | ||
517 |
=head2 build_tx |
|
518 | ||
519 |
my $tx = $app->build_tx; |
|
520 | ||
521 |
Transaction builder, defaults to building a L<Mojo::Transaction::HTTP> |
|
522 |
object. |
|
523 | ||
524 |
=head2 defaults |
|
525 | ||
526 |
my $hash = $app->defaults; |
|
527 |
my $foo = $app->defaults('foo'); |
|
528 |
$app = $app->defaults({foo => 'bar'}); |
|
529 |
$app = $app->defaults(foo => 'bar'); |
|
530 | ||
531 |
Default values for L<Mojolicious::Controller/"stash">, assigned for every new |
|
532 |
request. |
|
533 | ||
534 |
# Remove value |
|
535 |
my $foo = delete $app->defaults->{foo}; |
|
536 | ||
537 |
=head2 dispatch |
|
538 | ||
539 |
$app->dispatch(Mojolicious::Controller->new); |
|
540 | ||
541 |
The heart of every L<Mojolicious> application, calls the L</"static"> and |
|
542 |
L</"routes"> dispatchers for every request and passes them a |
|
543 |
L<Mojolicious::Controller> object. |
|
544 | ||
545 |
=head2 handler |
|
546 | ||
547 |
$app->handler(Mojo::Transaction::HTTP->new); |
|
548 |
$app->handler(Mojolicious::Controller->new); |
|
549 | ||
550 |
Sets up the default controller and calls process for every request. |
|
551 | ||
552 |
=head2 helper |
|
553 | ||
554 |
$app->helper(foo => sub {...}); |
|
555 | ||
556 |
Add a new helper that will be available as a method of the controller object |
|
557 |
and the application object, as well as a function in C<ep> templates. |
|
558 | ||
559 |
# Helper |
|
560 |
$app->helper(cache => sub { state $cache = {} }); |
|
561 | ||
562 |
# Controller/Application |
|
563 |
$self->cache->{foo} = 'bar'; |
|
564 |
my $result = $self->cache->{foo}; |
|
565 | ||
566 |
# Template |
|
567 |
% cache->{foo} = 'bar'; |
|
568 |
%= cache->{foo} |
|
569 | ||
570 |
=head2 hook |
|
571 | ||
572 |
$app->hook(after_dispatch => sub {...}); |
|
573 | ||
574 |
Extend L<Mojolicious> with hooks, which allow code to be shared with all |
|
575 |
requests indiscriminately, for a full list of available hooks see L</"HOOKS">. |
|
576 | ||
577 |
# Dispatchers will not run if there's already a response code defined |
|
578 |
$app->hook(before_dispatch => sub { |
|
579 |
my $c = shift; |
|
580 |
$c->render(text => 'Skipped static file server and router!') |
|
581 |
if $c->req->url->path->to_route =~ /do_not_dispatch/; |
|
582 |
}); |
|
583 | ||
584 |
=head2 plugin |
|
585 | ||
586 |
$app->plugin('some_thing'); |
|
587 |
$app->plugin('some_thing', foo => 23); |
|
588 |
$app->plugin('some_thing', {foo => 23}); |
|
589 |
$app->plugin('SomeThing'); |
|
590 |
$app->plugin('SomeThing', foo => 23); |
|
591 |
$app->plugin('SomeThing', {foo => 23}); |
|
592 |
$app->plugin('MyApp::Plugin::SomeThing'); |
|
593 |
$app->plugin('MyApp::Plugin::SomeThing', foo => 23); |
|
594 |
$app->plugin('MyApp::Plugin::SomeThing', {foo => 23}); |
|
595 | ||
596 |
Load a plugin, for a full list of example plugins included in the |
|
597 |
L<Mojolicious> distribution see L<Mojolicious::Plugins/"PLUGINS">. |
|
598 | ||
599 |
=head2 start |
|
600 | ||
601 |
$app->start; |
|
602 |
$app->start(@ARGV); |
|
603 | ||
604 |
Start the command line interface for your application, for a full list of |
|
605 |
commands available by default see L<Mojolicious::Commands/"COMMANDS">. |
|
606 | ||
607 |
# Always start daemon and ignore @ARGV |
|
608 |
$app->start('daemon', '-l', 'http://*:8080'); |
|
609 | ||
610 |
=head2 startup |
|
611 | ||
612 |
$app->startup; |
|
613 | ||
614 |
This is your main hook into the application, it will be called at application |
|
615 |
startup. Meant to be overloaded in a subclass. |
|
616 | ||
617 |
sub startup { |
|
618 |
my $self = shift; |
|
619 |
... |
|
620 |
} |
|
621 | ||
622 |
=head1 HELPERS |
|
623 | ||
624 |
In addition to the attributes and methods above you can also call helpers on |
|
625 |
L<Mojolicious> objects. This includes all helpers from |
|
626 |
L<Mojolicious::Plugin::DefaultHelpers> and L<Mojolicious::Plugin::TagHelpers>. |
|
627 |
Note that application helpers are always called with a new default controller |
|
628 |
object, so they can't depend on or change controller state, which includes |
|
629 |
request, response and stash. |
|
630 | ||
631 |
$app->log->debug($app->dumper({foo => 'bar'})); |
|
632 | ||
633 |
=head1 BUNDLED FILES |
|
634 | ||
635 |
The L<Mojolicious> distribution includes a few files with different licenses |
|
636 |
that have been bundled for internal use. |
|
637 | ||
638 |
=head2 Mojolicious Artwork |
|
639 | ||
640 |
Copyright (C) 2010-2013, Sebastian Riedel. |
|
641 | ||
642 |
Licensed under the CC-SA License, Version 3.0 |
|
643 |
L<http://creativecommons.org/licenses/by-sa/3.0>. |
|
644 | ||
645 |
=head2 jQuery |
|
646 | ||
647 |
Copyright (C) 2005, 2013 jQuery Foundation, Inc. |
|
648 | ||
649 |
Licensed under the MIT License, L<http://creativecommons.org/licenses/MIT>. |
|
650 | ||
651 |
=head2 prettify.js |
|
652 | ||
653 |
Copyright (C) 2006, 2013 Google Inc. |
|
654 | ||
655 |
Licensed under the Apache License, Version 2.0 |
|
656 |
L<http://www.apache.org/licenses/LICENSE-2.0>. |
|
657 | ||
658 |
=head1 CODE NAMES |
|
659 | ||
660 |
Every major release of L<Mojolicious> has a code name, these are the ones that |
|
661 |
have been used in the past. |
|
662 | ||
663 |
4.0, C<Top Hat> (u1F3A9) |
|
664 | ||
665 |
3.0, C<Rainbow> (u1F308) |
|
666 | ||
667 |
2.0, C<Leaf Fluttering In Wind> (u1F343) |
|
668 | ||
669 |
1.4, C<Smiling Face With Sunglasses> (u1F60E) |
|
670 | ||
671 |
1.3, C<Tropical Drink> (u1F379) |
|
672 | ||
673 |
1.1, C<Smiling Cat Face With Heart-Shaped Eyes> (u1F63B) |
|
674 | ||
675 |
1.0, C<Snowflake> (u2744) |
|
676 | ||
677 |
0.999930, C<Hot Beverage> (u2615) |
|
678 | ||
679 |
0.999927, C<Comet> (u2604) |
|
680 | ||
681 |
0.999920, C<Snowman> (u2603) |
|
682 | ||
683 |
=head1 SPONSORS |
|
684 | ||
685 |
Some of the work on this distribution has been sponsored by |
|
686 |
L<The Perl Foundation|http://www.perlfoundation.org>, thank you! |
|
687 | ||
688 |
=head1 PROJECT FOUNDER |
|
689 | ||
690 |
Sebastian Riedel, C<sri@cpan.org> |
|
691 | ||
692 |
=head1 CORE DEVELOPERS |
|
693 | ||
694 |
Current members of the core team in alphabetical order: |
|
695 | ||
696 |
=over 2 |
|
697 | ||
698 |
Abhijit Menon-Sen, C<ams@cpan.org> |
|
699 | ||
700 |
Glen Hinkle, C<tempire@cpan.org> |
|
701 | ||
702 |
Joel Berger, C<jberger@cpan.org> |
|
703 | ||
704 |
Marcus Ramberg, C<mramberg@cpan.org> |
|
705 | ||
706 |
=back |
|
707 | ||
708 |
=head1 CREDITS |
|
709 | ||
710 |
In alphabetical order: |
|
711 | ||
712 |
=over 2 |
|
713 | ||
714 |
Adam Kennedy |
|
715 | ||
716 |
Adriano Ferreira |
|
717 | ||
718 |
Al Newkirk |
|
719 | ||
720 |
Alex Efros |
|
721 | ||
722 |
Alex Salimon |
|
723 | ||
724 |
Alexey Likhatskiy |
|
725 | ||
726 |
Anatoly Sharifulin |
|
727 | ||
728 |
Andre Vieth |
|
729 | ||
730 |
Andreas Jaekel |
|
731 | ||
732 |
Andreas Koenig |
|
733 | ||
734 |
Andrew Fresh |
|
735 | ||
736 |
Andrey Khozov |
|
737 | ||
738 |
Andy Grundman |
|
739 | ||
740 |
Aristotle Pagaltzis |
|
741 | ||
742 |
Ashley Dev |
|
743 | ||
744 |
Ask Bjoern Hansen |
|
745 | ||
746 |
Audrey Tang |
|
747 | ||
748 |
Ben van Staveren |
|
749 | ||
750 |
Benjamin Erhart |
|
751 | ||
752 |
Bernhard Graf |
|
753 | ||
754 |
Breno G. de Oliveira |
|
755 | ||
756 |
Brian Duggan |
|
757 | ||
758 |
Brian Medley |
|
759 | ||
760 |
Burak Gursoy |
|
761 | ||
762 |
Ch Lamprecht |
|
763 | ||
764 |
Charlie Brady |
|
765 | ||
766 |
Chas. J. Owens IV |
|
767 | ||
768 |
Christian Hansen |
|
769 | ||
770 |
chromatic |
|
771 | ||
772 |
Curt Tilmes |
|
773 | ||
774 |
Daniel Kimsey |
|
775 | ||
776 |
Danijel Tasov |
|
777 | ||
778 |
Danny Thomas |
|
779 | ||
780 |
David Davis |
|
781 | ||
782 |
David Webb |
|
783 | ||
784 |
Diego Kuperman |
|
785 | ||
786 |
Dmitriy Shalashov |
|
787 | ||
788 |
Dmitry Konstantinov |
|
789 | ||
790 |
Dominik Jarmulowicz |
|
791 | ||
792 |
Dominique Dumont |
|
793 | ||
794 |
Douglas Christopher Wilson |
|
795 | ||
796 |
Eugene Toropov |
|
797 | ||
798 |
Gisle Aas |
|
799 | ||
800 |
Graham Barr |
|
801 | ||
802 |
Henry Tang |
|
803 | ||
804 |
Hideki Yamamura |
|
805 | ||
806 |
Ian Goodacre |
|
807 | ||
808 |
Ilya Chesnokov |
|
809 | ||
810 |
James Duncan |
|
811 | ||
812 |
Jan Henning Thorsen |
|
813 | ||
814 |
Jan Jona Javorsek |
|
815 | ||
816 |
Jan Schmidt |
|
817 | ||
818 |
Jaroslav Muhin |
|
819 | ||
820 |
Jesse Vincent |
|
821 | ||
822 |
Johannes Plunien |
|
823 | ||
824 |
John Kingsley |
|
825 | ||
826 |
Jonathan Yu |
|
827 | ||
828 |
Josh Leder |
|
829 | ||
830 |
Kazuhiro Shibuya |
|
831 | ||
832 |
Kevin Old |
|
833 | ||
834 |
Kitamura Akatsuki |
|
835 | ||
836 |
Lars Balker Rasmussen |
|
837 | ||
838 |
Leon Brocard |
|
839 | ||
840 |
Magnus Holm |
|
841 | ||
842 |
Maik Fischer |
|
843 | ||
844 |
Mark Stosberg |
|
845 | ||
846 |
Marty Tennison |
|
847 | ||
848 |
Matthew Lineen |
|
849 | ||
850 |
Maksym Komar |
|
851 | ||
852 |
Maxim Vuets |
|
853 | ||
854 |
Michael Harris |
|
855 | ||
856 |
Mike Magowan |
|
857 | ||
858 |
Mirko Westermeier |
|
859 | ||
860 |
Mons Anderson |
|
861 | ||
862 |
Moritz Lenz |
|
863 | ||
864 |
Neil Watkiss |
|
865 | ||
866 |
Nic Sandfield |
|
867 | ||
868 |
Nils Diewald |
|
869 | ||
870 |
Oleg Zhelo |
|
871 | ||
872 |
Pascal Gaudette |
|
873 | ||
874 |
Paul Evans |
|
875 | ||
876 |
Paul Tomlin |
|
877 | ||
878 |
Pavel Shaydo |
|
879 | ||
880 |
Pedro Melo |
|
881 | ||
882 |
Peter Edwards |
|
883 | ||
884 |
Pierre-Yves Ritschard |
|
885 | ||
886 |
Quentin Carbonneaux |
|
887 | ||
888 |
Rafal Pocztarski |
|
889 | ||
890 |
Randal Schwartz |
|
891 | ||
892 |
Robert Hicks |
|
893 | ||
894 |
Robin Lee |
|
895 | ||
896 |
Roland Lammel |
|
897 | ||
898 |
Ryan Jendoubi |
|
899 | ||
900 |
Sascha Kiefer |
|
901 | ||
902 |
Scott Wiersdorf |
|
903 | ||
904 |
Sergey Zasenko |
|
905 | ||
906 |
Simon Bertrang |
|
907 | ||
908 |
Simone Tampieri |
|
909 | ||
910 |
Shu Cho |
|
911 | ||
912 |
Skye Shaw |
|
913 | ||
914 |
Stanis Trendelenburg |
|
915 | ||
916 |
Stephane Este-Gracias |
|
917 | ||
918 |
Tatsuhiko Miyagawa |
|
919 | ||
920 |
Terrence Brannon |
|
921 | ||
922 |
Tomas Znamenacek |
|
923 | ||
924 |
Ulrich Habel |
|
925 | ||
926 |
Ulrich Kautz |
|
927 | ||
928 |
Uwe Voelker |
|
929 | ||
930 |
Viacheslav Tykhanovskyi |
|
931 | ||
932 |
Victor Engmark |
|
933 | ||
934 |
Viliam Pucik |
|
935 | ||
936 |
Wes Cravens |
|
937 | ||
938 |
Yaroslav Korshak |
|
939 | ||
940 |
Yuki Kimoto |
|
941 | ||
942 |
Zak B. Elep |
|
943 | ||
944 |
=back |
|
945 | ||
946 |
=head1 COPYRIGHT AND LICENSE |
|
947 | ||
948 |
Copyright (C) 2008-2013, Sebastian Riedel. |
|
949 | ||
950 |
This program is free software, you can redistribute it and/or modify it under |
|
951 |
the terms of the Artistic License version 2.0. |
|
952 | ||
953 |
=head1 SEE ALSO |
|
954 | ||
955 |
L<Mojolicious::Guides>, L<http://mojolicio.us>. |
|
956 | ||
957 |
=cut |