In Catalyst::Test, don't mangle headers of non-HTML responses. RT#79043
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Controller.pm
CommitLineData
5ee249f2 1package Catalyst::Controller;
2
ae29b412 3use Moose;
eff60019 4use Class::MOP;
c6392ad5 5use Class::Load ':all';
eff60019 6use String::RewritePrefix;
a58af53d 7use Moose::Util qw/find_meta/;
eff60019 8use List::Util qw/first/;
4f4ab5b4 9use List::MoreUtils qw/uniq/;
ae29b412 10use namespace::clean -except => 'meta';
11
ba545c13 12BEGIN { extends qw/Catalyst::Component MooseX::MethodAttributes::Inheritable/; }
234763d4 13
cf37d21a 14use MooseX::MethodAttributes;
234763d4 15use Catalyst::Exception;
16use Catalyst::Utils;
ae29b412 17
18with 'Catalyst::Component::ApplicationAttribute';
19
aea897b2 20has path_prefix => (
21 is => 'rw',
22 isa => 'Str',
23 init_arg => 'path',
24 predicate => 'has_path_prefix',
25);
26
27has action_namespace => (
28 is => 'rw',
29 isa => 'Str',
30 init_arg => 'namespace',
31 predicate => 'has_action_namespace',
32);
33
34has actions => (
35 accessor => '_controller_actions',
36 isa => 'HashRef',
37 init_arg => undef,
38);
ae29b412 39
eff60019 40has _action_role_args => (
41 traits => [qw(Array)],
42 isa => 'ArrayRef[Str]',
43 init_arg => 'action_roles',
44 default => sub { [] },
45 handles => {
46 _action_role_args => 'elements',
47 },
48);
49
50has _action_roles => (
51 traits => [qw(Array)],
52 isa => 'ArrayRef[RoleName]',
53 init_arg => undef,
54 lazy => 1,
55 builder => '_build__action_roles',
56 handles => {
57 _action_roles => 'elements',
58 },
59);
60
bf7c9c87 61has action_args => (is => 'ro');
62
bdd6684e 63# ->config(actions => { '*' => ...
64has _all_actions_attributes => (
65 is => 'ro',
66 isa => 'HashRef',
67 init_arg => undef,
68 lazy => 1,
69 builder => '_build__all_actions_attributes',
70);
71
7f22a5aa 72sub BUILD {
73 my ($self, $args) = @_;
ae29b412 74 my $action = delete $args->{action} || {};
75 my $actions = delete $args->{actions} || {};
7f22a5aa 76 my $attr_value = $self->merge_config_hashes($actions, $action);
77 $self->_controller_actions($attr_value);
5ee249f2 78
bdd6684e 79 # trigger lazy builder
80 $self->_all_actions_attributes;
eff60019 81 $self->_action_roles;
82}
83
84sub _build__action_roles {
85 my $self = shift;
86 my @roles = $self->_expand_role_shortname($self->_action_role_args);
c6392ad5 87 load_class($_) for @roles;
eff60019 88 return \@roles;
bdd6684e 89}
d0e5dfb5 90
bdd6684e 91sub _build__all_actions_attributes {
92 my ($self) = @_;
93 delete $self->_controller_actions->{'*'} || {};
94}
d0e5dfb5 95
5ee249f2 96=head1 NAME
97
98Catalyst::Controller - Catalyst Controller base class
99
100=head1 SYNOPSIS
101
234763d4 102 package MyApp::Controller::Search
a269e0c2 103 use base qw/Catalyst::Controller/;
234763d4 104
27ae4114 105 sub foo : Local {
85d9fce6 106 my ($self,$c,@args) = @_;
27ae4114 107 ...
234763d4 108 } # Dispatches to /search/foo
5ee249f2 109
110=head1 DESCRIPTION
111
a269e0c2 112Controllers are where the actions in the Catalyst framework
113reside. Each action is represented by a function with an attribute to
114identify what kind of action it is. See the L<Catalyst::Dispatcher>
115for more info about how Catalyst dispatches to actions.
234763d4 116
117=cut
118
ae29b412 119#I think both of these could be attributes. doesn't really seem like they need
120#to ble class data. i think that attributes +default would work just fine
eff60019 121__PACKAGE__->mk_classdata($_) for qw/_dispatch_steps _action_class _action_role_prefix/;
234763d4 122
123__PACKAGE__->_dispatch_steps( [qw/_BEGIN _AUTO _ACTION/] );
7b41db70 124__PACKAGE__->_action_class('Catalyst::Action');
eff60019 125__PACKAGE__->_action_role_prefix([ 'Catalyst::ActionRole::' ]);
234763d4 126
234763d4 127
128sub _DISPATCH : Private {
129 my ( $self, $c ) = @_;
130
131 foreach my $disp ( @{ $self->_dispatch_steps } ) {
132 last unless $c->forward($disp);
133 }
134
135 $c->forward('_END');
136}
137
138sub _BEGIN : Private {
139 my ( $self, $c ) = @_;
140 my $begin = ( $c->get_actions( 'begin', $c->namespace ) )[-1];
141 return 1 unless $begin;
142 $begin->dispatch( $c );
143 return !@{ $c->error };
144}
145
146sub _AUTO : Private {
147 my ( $self, $c ) = @_;
148 my @auto = $c->get_actions( 'auto', $c->namespace );
149 foreach my $auto (@auto) {
150 $auto->dispatch( $c );
151 return 0 unless $c->state;
152 }
153 return 1;
154}
155
156sub _ACTION : Private {
157 my ( $self, $c ) = @_;
158 if ( ref $c->action
159 && $c->action->can('execute')
53119b78 160 && defined $c->req->action )
234763d4 161 {
162 $c->action->dispatch( $c );
163 }
164 return !@{ $c->error };
165}
166
167sub _END : Private {
168 my ( $self, $c ) = @_;
169 my $end = ( $c->get_actions( 'end', $c->namespace ) )[-1];
170 return 1 unless $end;
171 $end->dispatch( $c );
172 return !@{ $c->error };
173}
174
234763d4 175sub action_for {
176 my ( $self, $name ) = @_;
177 my $app = ($self->isa('Catalyst') ? $self : $self->_application);
178 return $app->dispatcher->get_action($name, $self->action_namespace);
179}
180
27ae4114 181#my opinion is that this whole sub really should be a builder method, not
ae29b412 182#something that happens on every call. Anyone else disagree?? -- groditi
183## -- apparently this is all just waiting for app/ctx split
184around action_namespace => sub {
185 my $orig = shift;
234763d4 186 my ( $self, $c ) = @_;
ae29b412 187
df960201 188 my $class = ref($self) || $self;
189 my $appclass = ref($c) || $c;
ae29b412 190 if( ref($self) ){
191 return $self->$orig if $self->has_action_namespace;
192 } else {
df960201 193 return $class->config->{namespace} if exists $class->config->{namespace};
234763d4 194 }
234763d4 195
ae29b412 196 my $case_s;
197 if( $c ){
df960201 198 $case_s = $appclass->config->{case_sensitive};
ae29b412 199 } else {
200 if ($self->isa('Catalyst')) {
df960201 201 $case_s = $class->config->{case_sensitive};
ae29b412 202 } else {
203 if (ref $self) {
df960201 204 $case_s = ref($self->_application)->config->{case_sensitive};
ae29b412 205 } else {
206 confess("Can't figure out case_sensitive setting");
207 }
208 }
234763d4 209 }
ae29b412 210
8f6cebb2 211 my $namespace = Catalyst::Utils::class2prefix($self->catalyst_component_name, $case_s) || '';
ae29b412 212 $self->$orig($namespace) if ref($self);
213 return $namespace;
214};
215
216#Once again, this is probably better written as a builder method
217around path_prefix => sub {
218 my $orig = shift;
219 my $self = shift;
220 if( ref($self) ){
221 return $self->$orig if $self->has_path_prefix;
222 } else {
223 return $self->config->{path} if exists $self->config->{path};
224 }
225 my $namespace = $self->action_namespace(@_);
226 $self->$orig($namespace) if ref($self);
227 return $namespace;
228};
234763d4 229
9ab7d83d 230sub get_action_methods {
231 my $self = shift;
2bf074ab 232 my $meta = find_meta($self) || confess("No metaclass setup for $self");
69048792 233 confess(
234 sprintf "Metaclass %s for %s cannot support register_actions.",
235 ref $meta, $meta->name,
236 ) unless $meta->can('get_nearest_methods_with_attributes');
cf37d21a 237 my @methods = $meta->get_nearest_methods_with_attributes;
fa649eb7 238
239 # actions specified via config are also action_methods
240 push(
241 @methods,
242 map {
d0e78355 243 $meta->find_method_by_name($_)
e87273a4 244 || confess( sprintf 'Action "%s" is not available from controller %s',
245 $_, ref $self )
bdd6684e 246 } keys %{ $self->_controller_actions }
fa649eb7 247 ) if ( ref $self );
4f4ab5b4 248 return uniq @methods;
9ab7d83d 249}
234763d4 250
fa649eb7 251
234763d4 252sub register_actions {
253 my ( $self, $c ) = @_;
9ab7d83d 254 $self->register_action_methods( $c, $self->get_action_methods );
255}
256
257sub register_action_methods {
258 my ( $self, $c, @methods ) = @_;
8f6cebb2 259 my $class = $self->catalyst_component_name;
ae29b412 260 #this is still not correct for some reason.
234763d4 261 my $namespace = $self->action_namespace($c);
234763d4 262
f3c5b1c9 263 # FIXME - fugly
a202886b 264 if (!blessed($self) && $self eq $c && scalar(@methods)) {
f3c5b1c9 265 my @really_bad_methods = grep { ! /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/ } map { $_->name } @methods;
266 if (scalar(@really_bad_methods)) {
267 $c->log->warn("Action methods (" . join(', ', @really_bad_methods) . ") found defined in your application class, $self. This is deprecated, please move them into a Root controller.");
268 }
a202886b 269 }
d2598ac8 270
ba545c13 271 foreach my $method (@methods) {
272 my $name = $method->name;
d0f30dbc 273 # Horrible hack! All method metaclasses should have an attributes
274 # method, core Moose bug - see r13354.
10e970e4 275 my $attributes = $method->can('attributes') ? $method->attributes : [];
ba545c13 276 my $attrs = $self->_parse_attrs( $c, $name, @{ $attributes } );
234763d4 277 if ( $attrs->{Private} && ( keys %$attrs > 1 ) ) {
278 $c->log->debug( 'Bad action definition "'
ba545c13 279 . join( ' ', @{ $attributes } )
280 . qq/" for "$class->$name"/ )
234763d4 281 if $c->debug;
282 next;
283 }
bc677969 284 my $reverse = $namespace ? "${namespace}/${name}" : $name;
234763d4 285 my $action = $self->create_action(
ba545c13 286 name => $name,
287 code => $method->body,
234763d4 288 reverse => $reverse,
289 namespace => $namespace,
290 class => $class,
291 attributes => $attrs,
292 );
293
294 $c->dispatcher->register( $c, $action );
295 }
296}
297
eff60019 298sub _apply_action_class_roles {
299 my ($self, $class, @roles) = @_;
300
c6392ad5 301 load_class($_) for @roles;
eff60019 302 my $meta = Moose::Meta::Class->initialize($class)->create_anon_class(
303 superclasses => [$class],
304 roles => \@roles,
305 cache => 1,
306 );
307 $meta->add_method(meta => sub { $meta });
308
309 return $meta->name;
310}
311
f0a9b791 312sub action_class {
7b41db70 313 my $self = shift;
314 my %args = @_;
234763d4 315
316 my $class = (exists $args{attributes}{ActionClass}
f0a9b791 317 ? $args{attributes}{ActionClass}[0]
318 : $self->_action_class);
319
ae29b412 320 Class::MOP::load_class($class);
f0a9b791 321 return $class;
322}
323
324sub create_action {
325 my $self = shift;
326 my %args = @_;
a7e955ae 327
f0a9b791 328 my $class = $self->action_class(%args);
eff60019 329
330 load_class($class);
331 Moose->init_meta(for_class => $class)
332 unless Class::MOP::does_metaclass_exist($class);
333
334 unless ($args{name} =~ /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/) {
335 my @roles = $self->gather_action_roles(%args);
336 $class = $self->_apply_action_class_roles($class, @roles) if @roles;
337 }
338
bf7c9c87 339 my $action_args = (
340 ref($self)
341 ? $self->action_args
342 : $self->config->{action_args}
343 );
f0a9b791 344
a7e955ae 345 my %extra_args = (
346 %{ $action_args->{'*'} || {} },
347 %{ $action_args->{ $args{name} } || {} },
348 );
349
350 return $class->new({ %extra_args, %args });
234763d4 351}
352
eff60019 353sub gather_action_roles {
354 my ($self, %args) = @_;
355
356 return (
357 (blessed $self ? $self->_action_roles : ()),
358 @{ $args{attributes}->{Does} || [] },
359 );
360}
361
234763d4 362sub _parse_attrs {
363 my ( $self, $c, $name, @attrs ) = @_;
364
365 my %raw_attributes;
366
367 foreach my $attr (@attrs) {
368
369 # Parse out :Foo(bar) into Foo => bar etc (and arrayify)
370
371 if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.+?)\s*\))?$/ ) )
372 {
373
374 if ( defined $value ) {
375 ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
376 }
377 push( @{ $raw_attributes{$key} }, $value );
378 }
379 }
380
bdd6684e 381 my ($actions_config, $all_actions_config);
ae29b412 382 if( ref($self) ) {
bdd6684e 383 $actions_config = $self->_controller_actions;
384 # No, you're not getting actions => { '*' => ... } with actions in MyApp.
385 $all_actions_config = $self->_all_actions_attributes;
ae29b412 386 } else {
387 my $cfg = $self->config;
bdd6684e 388 $actions_config = $self->merge_config_hashes($cfg->{actions}, $cfg->{action});
389 $all_actions_config = {};
234763d4 390 }
391
ed9d06b6 392 %raw_attributes = (
393 %raw_attributes,
e95b2b49 394 # Note we deep copy array refs here to stop crapping on config
395 # when attributes are parsed. RT#65463
396 exists $actions_config->{$name} ? map { ref($_) eq 'ARRAY' ? [ @$_ ] : $_ } %{ $actions_config->{$name } } : (),
ed9d06b6 397 );
ae29b412 398
ed9d06b6 399 # Private actions with additional attributes will raise a warning and then
400 # be ignored. Adding '*' arguments to the default _DISPATCH / etc. methods,
401 # which are Private, will prevent those from being registered. They should
402 # probably be turned into :Actions instead, or we might want to otherwise
403 # disambiguate between those built-in internal actions and user-level
404 # Private ones.
bdd6684e 405 %raw_attributes = (%{ $all_actions_config }, %raw_attributes)
406 unless $raw_attributes{Private};
ae29b412 407
234763d4 408 my %final_attributes;
409
410 foreach my $key (keys %raw_attributes) {
411
412 my $raw = $raw_attributes{$key};
413
414 foreach my $value (ref($raw) eq 'ARRAY' ? @$raw : $raw) {
415
416 my $meth = "_parse_${key}_attr";
ae29b412 417 if ( my $code = $self->can($meth) ) {
418 ( $key, $value ) = $self->$code( $c, $name, $value );
234763d4 419 }
420 push( @{ $final_attributes{$key} }, $value );
421 }
422 }
423
424 return \%final_attributes;
425}
426
427sub _parse_Global_attr {
428 my ( $self, $c, $name, $value ) = @_;
429 return $self->_parse_Path_attr( $c, $name, "/$name" );
430}
431
432sub _parse_Absolute_attr { shift->_parse_Global_attr(@_); }
433
434sub _parse_Local_attr {
435 my ( $self, $c, $name, $value ) = @_;
436 return $self->_parse_Path_attr( $c, $name, $name );
437}
438
439sub _parse_Relative_attr { shift->_parse_Local_attr(@_); }
440
441sub _parse_Path_attr {
442 my ( $self, $c, $name, $value ) = @_;
53119b78 443 $value = '' if !defined $value;
234763d4 444 if ( $value =~ m!^/! ) {
445 return ( 'Path', $value );
446 }
447 elsif ( length $value ) {
448 return ( 'Path', join( '/', $self->path_prefix($c), $value ) );
449 }
450 else {
451 return ( 'Path', $self->path_prefix($c) );
452 }
453}
454
455sub _parse_Regex_attr {
456 my ( $self, $c, $name, $value ) = @_;
457 return ( 'Regex', $value );
458}
459
460sub _parse_Regexp_attr { shift->_parse_Regex_attr(@_); }
461
462sub _parse_LocalRegex_attr {
463 my ( $self, $c, $name, $value ) = @_;
464 unless ( $value =~ s/^\^// ) { $value = "(?:.*?)$value"; }
19c01ee1 465
466 my $prefix = $self->path_prefix( $c );
467 $prefix .= '/' if length( $prefix );
27ae4114 468
19c01ee1 469 return ( 'Regex', "^${prefix}${value}" );
234763d4 470}
471
472sub _parse_LocalRegexp_attr { shift->_parse_LocalRegex_attr(@_); }
473
f3107403 474sub _parse_Chained_attr {
475 my ($self, $c, $name, $value) = @_;
476
477 if (defined($value) && length($value)) {
478 if ($value eq '.') {
479 $value = '/'.$self->action_namespace($c);
fb56008f 480 } elsif (my ($rel, $rest) = $value =~ /^((?:\.{2}\/)+)(.*)$/) {
eb270c30 481 my @parts = split '/', $self->action_namespace($c);
fb56008f 482 my @levels = split '/', $rel;
483
484 $value = '/'.join('/', @parts[0 .. $#parts - @levels], $rest);
f3107403 485 } elsif ($value !~ m/^\//) {
486 my $action_ns = $self->action_namespace($c);
487
488 if ($action_ns) {
489 $value = '/'.join('/', $action_ns, $value);
490 } else {
491 $value = '/'.$value; # special case namespace '' (root)
492 }
493 }
494 } else {
495 $value = '/'
496 }
497
498 return Chained => $value;
499}
500
9356b981 501sub _parse_ChainedParent_attr {
502 my ($self, $c, $name, $value) = @_;
503 return $self->_parse_Chained_attr($c, $name, '../'.$name);
504}
505
e5d2cfdb 506sub _parse_PathPrefix_attr {
02825551 507 my ( $self, $c ) = @_;
508 return PathPart => $self->path_prefix($c);
e5d2cfdb 509}
510
234763d4 511sub _parse_ActionClass_attr {
512 my ( $self, $c, $name, $value ) = @_;
5d8129e9 513 my $appname = $self->_application;
514 $value = Catalyst::Utils::resolve_namespace($appname . '::Action', $self->_action_class, $value);
234763d4 515 return ( 'ActionClass', $value );
516}
517
9287719b 518sub _parse_MyAction_attr {
519 my ( $self, $c, $name, $value ) = @_;
520
521 my $appclass = Catalyst::Utils::class2appclass($self);
522 $value = "${appclass}::Action::${value}";
234763d4 523
9287719b 524 return ( 'ActionClass', $value );
525}
234763d4 526
eff60019 527sub _parse_Does_attr {
528 my ($self, $app, $name, $value) = @_;
529 return Does => $self->_expand_role_shortname($value);
530}
531
532sub _expand_role_shortname {
533 my ($self, @shortnames) = @_;
534 my $app = $self->_application;
535
536 my $prefix = $self->can('_action_role_prefix') ? $self->_action_role_prefix : ['Catalyst::ActionRole::'];
537 my @prefixes = (qq{${app}::ActionRole::}, @$prefix);
538
539 return String::RewritePrefix->rewrite(
540 { '' => sub {
c6392ad5 541 my $loaded = load_first_existing_class(
eff60019 542 map { "$_$_[0]" } @prefixes
543 );
544 return first { $loaded =~ /^$_/ }
545 sort { length $b <=> length $a } @prefixes;
546 },
547 '~' => $prefixes[0],
548 '+' => '' },
549 @shortnames,
550 );
551}
552
ae29b412 553__PACKAGE__->meta->make_immutable;
554
234763d4 5551;
556
557__END__
558
559=head1 CONFIGURATION
560
a269e0c2 561Like any other L<Catalyst::Component>, controllers have a config hash,
562accessible through $self->config from the controller actions. Some
563settings are in use by the Catalyst framework:
234763d4 564
565=head2 namespace
566
a269e0c2 567This specifies the internal namespace the controller should be bound
568to. By default the controller is bound to the URI version of the
569controller name. For instance controller 'MyApp::Controller::Foo::Bar'
570will be bound to 'foo/bar'. The default Root controller is an example
571of setting namespace to '' (the null string).
234763d4 572
27ae4114 573=head2 path
234763d4 574
575Sets 'path_prefix', as described below.
576
0a2577a8 577=head2 action
578
579Allows you to set the attributes that the dispatcher creates actions out of.
580This allows you to do 'rails style routes', or override some of the
f4dda4a8 581attribute definitions of actions composed from Roles.
0a2577a8 582You can set arguments globally (for all actions of the controller) and
583specifically (for a single action).
584
585 __PACKAGE__->config(
586 action => {
587 '*' => { Chained => 'base', Args => 0 },
588 base => { Chained => '/', PathPart => '', CaptureArgs => 0 },
589 },
590 );
591
592In the case above every sub in the package would be made into a Chain
593endpoint with a URI the same as the sub name for each sub, chained
594to the sub named C<base>. Ergo dispatch to C</example> would call the
595C<base> method, then the C<example> method.
596
c8136648 597=head2 action_args
598
4d4e5de8 599Allows you to set constructor arguments on your actions. You can set arguments
0a2577a8 600globally and specifically (as above).
601This is particularly useful when using C<ActionRole>s
b939ae6b 602(L<Catalyst::Controller::ActionRole>) and custom C<ActionClass>es.
c8136648 603
b939ae6b 604 __PACKAGE__->config(
c8136648 605 action_args => {
b939ae6b 606 '*' => { globalarg1 => 'hello', globalarg2 => 'goodbye' },
607 'specific_action' => { customarg => 'arg1' },
cea3f28a 608 },
b939ae6b 609 );
cea3f28a 610
b939ae6b 611In the case above the action class associated with C<specific_action> would get
612passed the following arguments, in addition to the normal action constructor
613arguments, when it is instantiated:
614
615 (globalarg1 => 'hello', globalarg2 => 'goodbye', customarg => 'arg1')
c8136648 616
234763d4 617=head1 METHODS
618
c4d02967 619=head2 BUILDARGS ($app, @args)
234763d4 620
c4d02967 621From L<Catalyst::Component::ApplicationAttribute>, stashes the application
622instance as $self->_application.
234763d4 623
624=head2 $self->action_for('name')
625
a269e0c2 626Returns the Catalyst::Action object (if any) for a given method name
627in this component.
234763d4 628
234763d4 629=head2 $self->action_namespace($c)
630
a269e0c2 631Returns the private namespace for actions in this component. Defaults
632to a value from the controller name (for
633e.g. MyApp::Controller::Foo::Bar becomes "foo/bar") or can be
634overridden from the "namespace" config key.
234763d4 635
636
637=head2 $self->path_prefix($c)
638
e5d2cfdb 639Returns the default path prefix for :PathPrefix, :Local, :LocalRegex and
640relative :Path actions in this component. Defaults to the action_namespace or
a269e0c2 641can be overridden from the "path" config key.
234763d4 642
c4d02967 643=head2 $self->register_actions($c)
644
645Finds all applicable actions for this component, creates
646Catalyst::Action objects (using $self->create_action) for them and
647registers them with $c->dispatcher.
648
649=head2 $self->get_action_methods()
650
651Returns a list of L<Moose::Meta::Method> objects, doing the
652L<MooseX::MethodAttributes::Role::Meta::Method> role, which are the set of
653action methods for this package.
654
655=head2 $self->register_action_methods($c, @methods)
656
657Creates action objects for a set of action methods using C< create_action >,
658and registers them with the dispatcher.
659
f0a9b791 660=head2 $self->action_class(%args)
661
662Used when a controller is creating an action to determine the correct base
24d2dfaf 663action class to use.
f0a9b791 664
234763d4 665=head2 $self->create_action(%args)
666
a269e0c2 667Called with a hash of data to be use for construction of a new
668Catalyst::Action (or appropriate sub/alternative class) object.
234763d4 669
eff60019 670=head2 $self->gather_action_roles(\%action_args)
671
672Gathers the list of roles to apply to an action with the given %action_args.
673
a269e0c2 674=head2 $self->_application
234763d4 675
676=head2 $self->_app
677
678Returns the application instance stored by C<new()>
5ee249f2 679
0bf7ab71 680=head1 AUTHORS
5ee249f2 681
0bf7ab71 682Catalyst Contributors, see Catalyst.pm
5ee249f2 683
684=head1 COPYRIGHT
685
536bee89 686This library is free software. You can redistribute it and/or modify
a269e0c2 687it under the same terms as Perl itself.
5ee249f2 688
689=cut