1 package Catalyst::Controller;
5 use Class::Load ':all';
6 use String::RewritePrefix;
7 use Moose::Util qw/find_meta/;
8 use List::Util qw/first uniq/;
9 use namespace::clean -except => 'meta';
12 extends qw/Catalyst::Component/;
13 with qw/MooseX::MethodAttributes::Role::AttrContainer::Inheritable/;
16 use MooseX::MethodAttributes;
17 use Catalyst::Exception;
20 with 'Catalyst::Component::ApplicationAttribute';
26 predicate => 'has_path_prefix',
29 has action_namespace => (
32 init_arg => 'namespace',
33 predicate => 'has_action_namespace',
37 accessor => '_controller_actions',
42 has _action_role_args => (
43 traits => [qw(Array)],
44 isa => 'ArrayRef[Str]',
45 init_arg => 'action_roles',
46 default => sub { [] },
48 _action_role_args => 'elements',
52 has _action_roles => (
53 traits => [qw(Array)],
54 isa => 'ArrayRef[RoleName]',
57 builder => '_build__action_roles',
59 _action_roles => 'elements',
63 has action_args => (is => 'ro');
65 # ->config(actions => { '*' => ...
66 has _all_actions_attributes => (
71 builder => '_build__all_actions_attributes',
75 my ($self, $args) = @_;
76 my $action = delete $args->{action} || {};
77 my $actions = delete $args->{actions} || {};
78 my $attr_value = $self->merge_config_hashes($actions, $action);
79 $self->_controller_actions($attr_value);
81 # trigger lazy builder
82 $self->_all_actions_attributes;
86 sub _build__action_roles {
88 my @roles = $self->_expand_role_shortname($self->_action_role_args);
89 load_class($_) for @roles;
93 sub _build__all_actions_attributes {
95 delete $self->_controller_actions->{'*'} || {};
100 Catalyst::Controller - Catalyst Controller base class
104 package MyApp::Controller::Search
105 use base qw/Catalyst::Controller/;
108 my ($self,$c,@args) = @_;
110 } # Dispatches to /search/foo
114 Controllers are where the actions in the Catalyst framework
115 reside. Each action is represented by a function with an attribute to
116 identify what kind of action it is. See the L<Catalyst::Dispatcher>
117 for more info about how Catalyst dispatches to actions.
121 #I think both of these could be attributes. doesn't really seem like they need
122 #to be class data. i think that attributes +default would work just fine
123 __PACKAGE__->mk_classdata($_) for qw/_dispatch_steps _action_class _action_role_prefix/;
125 __PACKAGE__->_dispatch_steps( [qw/_BEGIN _AUTO _ACTION/] );
126 __PACKAGE__->_action_class('Catalyst::Action');
127 __PACKAGE__->_action_role_prefix([ 'Catalyst::ActionRole::' ]);
130 sub _DISPATCH : Private {
131 my ( $self, $c ) = @_;
133 foreach my $disp ( @{ $self->_dispatch_steps } ) {
134 last unless $c->forward($disp);
140 sub _BEGIN : Private {
141 my ( $self, $c ) = @_;
142 my $begin = ( $c->get_actions( 'begin', $c->namespace ) )[-1];
143 return 1 unless $begin;
144 $begin->dispatch( $c );
145 #If there is an error, all bets off
146 if( @{ $c->error }) {
147 return !@{ $c->error };
149 return $c->state || 1;
153 sub _AUTO : Private {
154 my ( $self, $c ) = @_;
155 my @auto = $c->get_actions( 'auto', $c->namespace );
156 foreach my $auto (@auto) {
157 # We FORCE the auto action user to explicitly return
158 # true. We need to do this since there's some auto
159 # users (Catalyst::Authentication::Credential::HTTP) that
160 # actually do a detach instead.
162 $auto->dispatch( $c );
163 return 0 unless $c->state;
165 return $c->state || 1;
168 sub _ACTION : Private {
169 my ( $self, $c ) = @_;
171 && $c->action->can('execute')
172 && defined $c->req->action )
174 $c->action->dispatch( $c );
176 #If there is an error, all bets off
177 if( @{ $c->error }) {
178 return !@{ $c->error };
180 return $c->state || 1;
185 my ( $self, $c ) = @_;
186 my $end = ( $c->get_actions( 'end', $c->namespace ) )[-1];
187 return 1 unless $end;
188 $end->dispatch( $c );
189 return !@{ $c->error };
193 my ( $self, $name ) = @_;
194 my $app = ($self->isa('Catalyst') ? $self : $self->_application);
195 return $app->dispatcher->get_action($name, $self->action_namespace);
198 #my opinion is that this whole sub really should be a builder method, not
199 #something that happens on every call. Anyone else disagree?? -- groditi
200 ## -- apparently this is all just waiting for app/ctx split
201 around action_namespace => sub {
203 my ( $self, $c ) = @_;
205 my $class = ref($self) || $self;
206 my $appclass = ref($c) || $c;
208 return $self->$orig if $self->has_action_namespace;
210 return $class->config->{namespace} if exists $class->config->{namespace};
215 $case_s = $appclass->config->{case_sensitive};
217 if ($self->isa('Catalyst')) {
218 $case_s = $class->config->{case_sensitive};
221 $case_s = ref($self->_application)->config->{case_sensitive};
223 confess("Can't figure out case_sensitive setting");
228 my $namespace = Catalyst::Utils::class2prefix($self->catalyst_component_name, $case_s) || '';
229 $self->$orig($namespace) if ref($self);
233 #Once again, this is probably better written as a builder method
234 around path_prefix => sub {
238 return $self->$orig if $self->has_path_prefix;
240 return $self->config->{path} if exists $self->config->{path};
242 my $namespace = $self->action_namespace(@_);
243 $self->$orig($namespace) if ref($self);
247 sub get_action_methods {
249 my $meta = find_meta($self) || confess("No metaclass setup for $self");
251 sprintf "Metaclass %s for %s cannot support register_actions.",
252 ref $meta, $meta->name,
253 ) unless $meta->can('get_nearest_methods_with_attributes');
254 my @methods = $meta->get_nearest_methods_with_attributes;
256 # actions specified via config are also action_methods
260 $meta->find_method_by_name($_)
261 || confess( sprintf 'Action "%s" is not available from controller %s',
263 } keys %{ $self->_controller_actions }
265 return uniq @methods;
269 sub register_actions {
270 my ( $self, $c ) = @_;
271 $self->register_action_methods( $c, $self->get_action_methods );
274 sub register_action_methods {
275 my ( $self, $c, @methods ) = @_;
276 my $class = $self->catalyst_component_name;
277 #this is still not correct for some reason.
278 my $namespace = $self->action_namespace($c);
281 if (!blessed($self) && $self eq $c && scalar(@methods)) {
282 my @really_bad_methods = grep { ! /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/ } map { $_->name } @methods;
283 if (scalar(@really_bad_methods)) {
284 $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.");
288 foreach my $method (@methods) {
289 my $name = $method->name;
290 # Horrible hack! All method metaclasses should have an attributes
291 # method, core Moose bug - see r13354.
292 my $attributes = $method->can('attributes') ? $method->attributes : [];
293 my $attrs = $self->_parse_attrs( $c, $name, @{ $attributes } );
294 if ( $attrs->{Private} && ( keys %$attrs > 1 ) ) {
295 $c->log->warn( 'Bad action definition "'
296 . join( ' ', @{ $attributes } )
297 . qq/" for "$class->$name"/ )
301 my $reverse = $namespace ? "${namespace}/${name}" : $name;
302 my $action = $self->create_action(
304 code => $method->body,
306 namespace => $namespace,
308 attributes => $attrs,
311 $c->dispatcher->register( $c, $action );
315 sub _apply_action_class_roles {
316 my ($self, $class, @roles) = @_;
318 load_class($_) for @roles;
319 my $meta = Moose::Meta::Class->initialize($class)->create_anon_class(
320 superclasses => [$class],
324 $meta->add_method(meta => sub { $meta });
333 my $class = (exists $args{attributes}{ActionClass}
334 ? $args{attributes}{ActionClass}[0]
335 : $self->_action_class);
345 my $class = $self->action_class(%args);
348 Moose->init_meta(for_class => $class)
349 unless Class::MOP::does_metaclass_exist($class);
351 unless ($args{name} =~ /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/) {
352 my @roles = $self->gather_action_roles(%args);
353 push @roles, $self->gather_default_action_roles(%args);
355 $class = $self->_apply_action_class_roles($class, @roles) if @roles;
361 : $self->config->{action_args}
365 %{ $action_args->{'*'} || {} },
366 %{ $action_args->{ $args{name} } || {} },
369 return $class->new({ %extra_args, %args });
372 sub gather_action_roles {
373 my ($self, %args) = @_;
375 (blessed $self ? $self->_action_roles : ()),
376 @{ $args{attributes}->{Does} || [] },
380 sub gather_default_action_roles {
381 my ($self, %args) = @_;
383 push @roles, 'Catalyst::ActionRole::HTTPMethods'
384 if $args{attributes}->{Method};
386 push @roles, 'Catalyst::ActionRole::ConsumesContent'
387 if $args{attributes}->{Consumes};
389 push @roles, 'Catalyst::ActionRole::Scheme'
390 if $args{attributes}->{Scheme};
392 push @roles, 'Catalyst::ActionRole::QueryMatching'
393 if $args{attributes}->{Query};
398 my ( $self, $c, $name, @attrs ) = @_;
402 foreach my $attr (@attrs) {
404 # Parse out :Foo(bar) into Foo => bar etc (and arrayify)
406 if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.+?)?\s*\))?$/ ) )
409 if ( defined $value ) {
410 ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
412 push( @{ $raw_attributes{$key} }, $value );
416 my ($actions_config, $all_actions_config);
418 $actions_config = $self->_controller_actions;
419 # No, you're not getting actions => { '*' => ... } with actions in MyApp.
420 $all_actions_config = $self->_all_actions_attributes;
422 my $cfg = $self->config;
423 $actions_config = $self->merge_config_hashes($cfg->{actions}, $cfg->{action});
424 $all_actions_config = {};
429 # Note we deep copy array refs here to stop crapping on config
430 # when attributes are parsed. RT#65463
431 exists $actions_config->{$name} ? map { ref($_) eq 'ARRAY' ? [ @$_ ] : $_ } %{ $actions_config->{$name } } : (),
434 # Private actions with additional attributes will raise a warning and then
435 # be ignored. Adding '*' arguments to the default _DISPATCH / etc. methods,
436 # which are Private, will prevent those from being registered. They should
437 # probably be turned into :Actions instead, or we might want to otherwise
438 # disambiguate between those built-in internal actions and user-level
440 %raw_attributes = (%{ $all_actions_config }, %raw_attributes)
441 unless $raw_attributes{Private};
443 my %final_attributes;
445 while (my ($key, $value) = each %raw_attributes){
446 my $new_attrs = $self->_parse_attr($c, $name, $key => $value );
447 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
450 return \%final_attributes;
454 my ($self, $c, $name, $key, $values) = @_;
456 my %final_attributes;
457 foreach my $value (ref($values) eq 'ARRAY' ? @$values : $values) {
458 my $meth = "_parse_${key}_attr";
459 if ( my $code = $self->can($meth) ) {
460 my %new_attrs = $self->$code( $c, $name, $value );
461 while (my ($new_key, $value) = each %new_attrs){
462 my $new_attrs = $key eq $new_key ?
463 { $new_key => [$value] } :
464 $self->_parse_attr($c, $name, $new_key => $value );
465 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
469 push( @{ $final_attributes{$key} }, $value );
473 return \%final_attributes;
476 sub _parse_Global_attr {
477 my ( $self, $c, $name, $value ) = @_;
478 # _parse_attr will call _parse_Path_attr for us
479 return Path => "/$name";
482 sub _parse_Absolute_attr { shift->_parse_Global_attr(@_); }
484 sub _parse_Local_attr {
485 my ( $self, $c, $name, $value ) = @_;
486 # _parse_attr will call _parse_Path_attr for us
487 return Path => $name;
490 sub _parse_Relative_attr { shift->_parse_Local_attr(@_); }
492 sub _parse_Path_attr {
493 my ( $self, $c, $name, $value ) = @_;
494 $value = '' if !defined $value;
495 if ( $value =~ m!^/! ) {
496 return ( 'Path', $value );
498 elsif ( length $value ) {
499 return ( 'Path', join( '/', $self->path_prefix($c), $value ) );
502 return ( 'Path', $self->path_prefix($c) );
506 sub _parse_Chained_attr {
507 my ($self, $c, $name, $value) = @_;
509 if (defined($value) && length($value)) {
511 $value = '/'.$self->action_namespace($c);
512 } elsif (my ($rel, $rest) = $value =~ /^((?:\.{2}\/)+)(.*)$/) {
513 my @parts = split '/', $self->action_namespace($c);
514 my @levels = split '/', $rel;
516 $value = '/'.join('/', @parts[0 .. $#parts - @levels], $rest);
517 } elsif ($value !~ m/^\//) {
518 my $action_ns = $self->action_namespace($c);
521 $value = '/'.join('/', $action_ns, $value);
523 $value = '/'.$value; # special case namespace '' (root)
530 return Chained => $value;
533 sub _parse_ChainedParent_attr {
534 my ($self, $c, $name, $value) = @_;
535 return $self->_parse_Chained_attr($c, $name, '../'.$name);
538 sub _parse_PathPrefix_attr {
539 my ( $self, $c ) = @_;
540 return PathPart => $self->path_prefix($c);
543 sub _parse_ActionClass_attr {
544 my ( $self, $c, $name, $value ) = @_;
545 my $appname = $self->_application;
546 $value = Catalyst::Utils::resolve_namespace($appname . '::Action', $self->_action_class, $value);
547 return ( 'ActionClass', $value );
550 sub _parse_MyAction_attr {
551 my ( $self, $c, $name, $value ) = @_;
553 my $appclass = Catalyst::Utils::class2appclass($self);
554 $value = "+${appclass}::Action::${value}";
556 return ( 'ActionClass', $value );
559 sub _parse_Does_attr {
560 my ($self, $app, $name, $value) = @_;
561 return Does => $self->_expand_role_shortname($value);
564 sub _parse_GET_attr { Method => 'GET' }
565 sub _parse_POST_attr { Method => 'POST' }
566 sub _parse_PUT_attr { Method => 'PUT' }
567 sub _parse_DELETE_attr { Method => 'DELETE' }
568 sub _parse_OPTIONS_attr { Method => 'OPTIONS' }
569 sub _parse_HEAD_attr { Method => 'HEAD' }
570 sub _parse_PATCH_attr { Method => 'PATCH' }
572 sub _expand_role_shortname {
573 my ($self, @shortnames) = @_;
574 my $app = $self->_application;
576 my $prefix = $self->can('_action_role_prefix') ? $self->_action_role_prefix : ['Catalyst::ActionRole::'];
577 my @prefixes = (qq{${app}::ActionRole::}, @$prefix);
579 return String::RewritePrefix->rewrite(
581 my $loaded = load_first_existing_class(
582 map { "$_$_[0]" } @prefixes
584 return first { $loaded =~ /^$_/ }
585 sort { length $b <=> length $a } @prefixes;
593 __PACKAGE__->meta->make_immutable;
601 Like any other L<Catalyst::Component>, controllers have a config hash,
602 accessible through $self->config from the controller actions. Some
603 settings are in use by the Catalyst framework:
607 This specifies the internal namespace the controller should be bound
608 to. By default the controller is bound to the URI version of the
609 controller name. For instance controller 'MyApp::Controller::Foo::Bar'
610 will be bound to 'foo/bar'. The default Root controller is an example
611 of setting namespace to '' (the null string).
615 Sets 'path_prefix', as described below.
619 Allows you to set the attributes that the dispatcher creates actions out of.
620 This allows you to do 'rails style routes', or override some of the
621 attribute definitions of actions composed from Roles.
622 You can set arguments globally (for all actions of the controller) and
623 specifically (for a single action).
627 '*' => { Chained => 'base', Args => 0 },
628 base => { Chained => '/', PathPart => '', CaptureArgs => 0 },
632 In the case above every sub in the package would be made into a Chain
633 endpoint with a URI the same as the sub name for each sub, chained
634 to the sub named C<base>. Ergo dispatch to C</example> would call the
635 C<base> method, then the C<example> method.
639 Allows you to set constructor arguments on your actions. You can set arguments
640 globally and specifically (as above).
641 This is particularly useful when using C<ActionRole>s
642 (L<Catalyst::Controller::ActionRole>) and custom C<ActionClass>es.
646 '*' => { globalarg1 => 'hello', globalarg2 => 'goodbye' },
647 'specific_action' => { customarg => 'arg1' },
651 In the case above the action class associated with C<specific_action> would get
652 passed the following arguments, in addition to the normal action constructor
653 arguments, when it is instantiated:
655 (globalarg1 => 'hello', globalarg2 => 'goodbye', customarg => 'arg1')
659 =head2 BUILDARGS ($app, @args)
661 From L<Catalyst::Component::ApplicationAttribute>, stashes the application
662 instance as $self->_application.
664 =head2 $self->action_for($action_name)
666 Returns the Catalyst::Action object (if any) for a given action in this
667 controller or relative to it. You may refer to actions in controllers
668 nested under the current controllers namespace, or in controllers 'up'
669 from the current controller namespace. For example:
671 package MyApp::Controller::One::Two;
672 use base 'Catalyst::Controller';
676 $self->action_for('foo'); # action 'foo' in Controller 'One::Two'
677 $self->action_for('three/bar'); # action 'bar' in Controller 'One::Two::Three'
678 $self->action_for('../boo'); # action 'boo' in Controller 'One'
681 This returns 'undef' if there is no action matching the requested action
682 name (after any path normalization) so you should check for this as needed.
684 =head2 $self->action_namespace($c)
686 Returns the private namespace for actions in this component. Defaults
687 to a value from the controller name (for
688 e.g. MyApp::Controller::Foo::Bar becomes "foo/bar") or can be
689 overridden from the "namespace" config key.
692 =head2 $self->path_prefix($c)
694 Returns the default path prefix for :PathPrefix, :Local and
695 relative :Path actions in this component. Defaults to the action_namespace or
696 can be overridden from the "path" config key.
698 =head2 $self->register_actions($c)
700 Finds all applicable actions for this component, creates
701 Catalyst::Action objects (using $self->create_action) for them and
702 registers them with $c->dispatcher.
704 =head2 $self->get_action_methods()
706 Returns a list of L<Moose::Meta::Method> objects, doing the
707 L<MooseX::MethodAttributes::Role::Meta::Method> role, which are the set of
708 action methods for this package.
710 =head2 $self->register_action_methods($c, @methods)
712 Creates action objects for a set of action methods using C< create_action >,
713 and registers them with the dispatcher.
715 =head2 $self->action_class(%args)
717 Used when a controller is creating an action to determine the correct base
720 =head2 $self->create_action(%args)
722 Called with a hash of data to be use for construction of a new
723 Catalyst::Action (or appropriate sub/alternative class) object.
725 =head2 $self->gather_action_roles(\%action_args)
727 Gathers the list of roles to apply to an action with the given %action_args.
729 =head2 $self->gather_default_action_roles(\%action_args)
731 returns a list of action roles to be applied based on core, builtin rules.
732 Currently only the L<Catalyst::ActionRole::HTTPMethods> role is applied
735 =head2 $self->_application
739 Returns the application instance stored by C<new()>
741 =head1 ACTION SUBROUTINE ATTRIBUTES
743 Please see L<Catalyst::Manual::Intro> for more details
745 Think of action attributes as a sort of way to record metadata about an action,
746 similar to how annotations work in other languages you might have heard of.
747 Generally L<Catalyst> uses these to influence how the dispatcher sees your
748 action and when it will run it in response to an incoming request. They can
749 also be used for other things. Here's a summary, but you should refer to the
750 linked manual page for additional help.
754 sub homepage :Global { ... }
756 A global action defined in any controller always runs relative to your root.
757 So the above is the same as:
759 sub myaction :Path("/homepage") { ... }
763 Status: Deprecated alias to L</Global>.
767 Alias to "Path("$action_name"). The following two actions are the same:
769 sub myaction :Local { ... }
770 sub myaction :Path('myaction') { ... }
774 Status: Deprecated alias to L</Local>
778 Handle various types of paths:
780 package MyApp::Controller::Baz {
784 sub myaction1 :Path { ... } # -> /baz
785 sub myaction2 :Path('foo') { ... } # -> /baz/foo
786 sub myaction2 :Path('/bar') { ... } # -> /bar
789 This is a general toolbox for attaching your action to a given path.
796 B<Status: Deprecated.> Use Chained methods or other techniques.
797 If you really depend on this, install the standalone
798 L<Catalyst::DispatchType::Regex> distribution.
800 A global way to match a give regular expression in the incoming request path.
806 B<Status: Deprecated.> Use Chained methods or other techniques.
807 If you really depend on this, install the standalone
808 L<Catalyst::DispatchType::Regex> distribution.
810 Like L</Regex> but scoped under the namespace of the containing controller
822 Allowed values for CaptureArgs is a single integer (CaptureArgs(2), meaning two
823 allowed) or you can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny>
824 named constraint such as CaptureArgs(Int,Str) would require two args with
825 the first being a Integer and the second a string. You may declare your own
826 custom type constraints and import them into the controller namespace:
828 package MyApp::Controller::Root;
831 use MooseX::MethodAttributes;
832 use MyApp::Types qw/Int/;
834 extends 'Catalyst::Controller';
836 sub chain_base :Chained(/) CaptureArgs(1) { }
838 sub any_priority_chain :Chained(chain_base) PathPart('') Args(1) { }
840 sub int_priority_chain :Chained(chain_base) PathPart('') Args(Int) { }
842 See L<Catalyst::RouteMatching> for more.
844 Please see L<Catalyst::DispatchType::Chained> for more.
848 Set the base class for the action, defaults to L</Catalyst::Action>. It is now
849 preferred to use L</Does>.
853 Set the ActionClass using a custom Action in your project namespace.
855 The following is exactly the same:
857 sub foo_action1 : Local ActionClass('+MyApp::Action::Bar') { ... }
858 sub foo_action2 : Local MyAction('Bar') { ... }
862 package MyApp::Controller::Zoo;
864 sub foo : Local Does('Buzz') { ... } # Catalyst::ActionRole::
865 sub bar : Local Does('~Buzz') { ... } # MyApp::ActionRole::Buzz
866 sub baz : Local Does('+MyApp::ActionRole::Buzz') { ... }
884 Sets the give action path to match the specified HTTP method, or via one of the
885 broadly accepted methods of overriding the 'true' method (see
886 L<Catalyst::ActionRole::HTTPMethods>).
890 When used with L</Path> indicates the number of arguments expected in
891 the path. However if no Args value is set, assumed to 'slurp' all
892 remaining path pars under this namespace.
894 Allowed values for Args is a single integer (Args(2), meaning two allowed) or you
895 can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny> named constraint such
896 as Args(Int,Str) would require two args with the first being a Integer and the
897 second a string. You may declare your own custom type constraints and import
898 them into the controller namespace:
900 package MyApp::Controller::Root;
903 use MooseX::MethodAttributes;
904 use MyApp::Types qw/Tuple Int Str StrMatch UserId/;
906 extends 'Catalyst::Controller';
908 sub user :Local Args(UserId) {
909 my ($self, $c, $int) = @_;
912 sub an_int :Local Args(Int) {
913 my ($self, $c, $int) = @_;
916 sub many_ints :Local Args(ArrayRef[Int]) {
917 my ($self, $c, @ints) = @_;
920 sub match :Local Args(StrMatch[qr{\d\d-\d\d-\d\d}]) {
921 my ($self, $c, $int) = @_;
924 If you choose not to use imported type constraints (like L<Type::Tiny>, or <MooseX::Types>
925 you may use L<Moose> 'stringy' types however just like when you use these types in your
926 declared attributes you must quote them:
928 sub my_moose_type :Local Args('Int') { ... }
930 If you use 'reference' type constraints (such as ArrayRef[Int]) that have an unknown
931 number of allowed matches, we set this the same way "Args" is. Please keep in mind
932 that actions with an undetermined number of args match at lower precedence than those
933 with a fixed number. You may use reference types such as Tuple from L<Types::Standard>
934 that allows you to fix the number of allowed args. For example Args(Tuple[Int,Int])
935 would be determined to be two args (or really the same as Args(Int,Int).) You may
936 find this useful for creating custom subtypes with complex matching rules that you
937 wish to reuse over many actions.
939 See L<Catalyst::RouteMatching> for more.
941 B<Note>: It is highly recommended to use L<Type::Tiny> for your type constraints over
942 other options. L<Type::Tiny> exposed a better meta data interface which allows us to
943 do more and better types of introspection driving tests and debugging.
945 =head2 Consumes('...')
947 Matches the current action against the content-type of the request. Typically
948 this is used when the request is a POST or PUT and you want to restrict the
949 submitted content type. For example, you might have an HTML for that either
950 returns classic url encoded form data, or JSON when Javascript is enabled. In
951 this case you may wish to match either incoming type to one of two different
952 actions, for properly processing.
956 sub is_json : Chained('start') Consumes('application/json') { ... }
957 sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
958 sub is_multipart : Chained('start') Consumes('multipart/form-data') { ... }
960 To reduce boilerplate, we include the following content type shortcuts:
964 sub is_json : Chained('start') Consume(JSON) { ... }
965 sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
966 sub is_multipart : Chained('start') Consumes(Multipart) { ... }
968 You may specify more than one match:
972 : Consumes('application/x-www-form-urlencoded')
973 : Consumes('multipart/form-data')
977 : Consumes(UrlEncoded)
978 : Consumes(Multipart)
980 Since it is a common case the shortcut C<HTMLForm> matches both
981 'application/x-www-form-urlencoded' and 'multipart/form-data'. Here's the full
982 list of available shortcuts:
984 JSON => 'application/json',
985 JS => 'application/javascript',
986 PERL => 'application/perl',
989 Plain => 'text/plain',
990 UrlEncoded => 'application/x-www-form-urlencoded',
991 Multipart => 'multipart/form-data',
992 HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
994 Please keep in mind that when dispatching, L<Catalyst> will match the first most
995 relevant case, so if you use the C<Consumes> attribute, you should place your
996 most accurate matches early in the Chain, and your 'catchall' actions last.
998 See L<Catalyst::ActionRole::ConsumesContent> for more.
1002 Allows you to specify a URI scheme for the action or action chain. For example
1003 you can required that a given path be C<https> or that it is a websocket endpoint
1004 C<ws> or C<wss>. For an action chain you may currently only have one defined
1007 package MyApp::Controller::Root;
1009 use base 'Catalyst::Controller';
1011 sub is_http :Path(scheme) Scheme(http) Args(0) {
1012 my ($self, $c) = @_;
1013 $c->response->body("is_http");
1016 sub is_https :Path(scheme) Scheme(https) Args(0) {
1017 my ($self, $c) = @_;
1018 $c->response->body("is_https");
1021 In the above example http://localhost/root/scheme would match the first
1022 action (is_http) but https://localhost/root/scheme would match the second.
1024 As an added benefit, if an action or action chain defines a Scheme, when using
1025 $c->uri_for the scheme of the generated URL will use what you define in the action
1026 or action chain (the current behavior is to set the scheme based on the current
1027 incoming request). This makes it easier to use uri_for on websites where some
1028 paths are secure and others are not. You may also use this to other schemes
1031 See L<Catalyst::ActionRole::Scheme> for more.
1033 =head1 OPTIONAL METHODS
1035 =head2 _parse_[$name]_attr
1037 Allows you to customize parsing of subroutine attributes.
1039 sub myaction1 :Path TwoArgs { ... }
1041 sub _parse_TwoArgs_attr {
1042 my ( $self, $c, $name, $value ) = @_;
1043 # $self -> controller instance
1048 Please note that this feature does not let you actually assign new functions
1049 to actions via subroutine attributes, but is really more for creating useful
1050 aliases to existing core and extended attributes, and transforms based on
1051 existing information (like from configuration). Code for actually doing
1052 something meaningful with the subroutine attributes will be located in the
1053 L<Catalyst::Action> classes (or your subclasses), L<Catalyst::Dispatcher> and
1054 in subclasses of L<Catalyst::DispatchType>. Remember these methods only get
1055 called basically once when the application is starting, not per request!
1059 Catalyst Contributors, see Catalyst.pm
1063 This library is free software. You can redistribute it and/or modify
1064 it under the same terms as Perl itself.