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/;
9 use List::MoreUtils qw/uniq/;
10 use Ref::Util qw(is_plain_arrayref);
11 use namespace::clean -except => 'meta';
14 extends qw/Catalyst::Component/;
15 with qw/MooseX::MethodAttributes::Role::AttrContainer::Inheritable/;
18 use MooseX::MethodAttributes;
19 use Catalyst::Exception;
22 with 'Catalyst::Component::ApplicationAttribute';
28 predicate => 'has_path_prefix',
31 has action_namespace => (
34 init_arg => 'namespace',
35 predicate => 'has_action_namespace',
39 accessor => '_controller_actions',
44 has _action_role_args => (
45 traits => [qw(Array)],
46 isa => 'ArrayRef[Str]',
47 init_arg => 'action_roles',
48 default => sub { [] },
50 _action_role_args => 'elements',
54 has _action_roles => (
55 traits => [qw(Array)],
56 isa => 'ArrayRef[RoleName]',
59 builder => '_build__action_roles',
61 _action_roles => 'elements',
65 has action_args => (is => 'ro');
67 # ->config(actions => { '*' => ...
68 has _all_actions_attributes => (
73 builder => '_build__all_actions_attributes',
77 my ($self, $args) = @_;
78 my $action = delete $args->{action} || {};
79 my $actions = delete $args->{actions} || {};
80 my $attr_value = $self->merge_config_hashes($actions, $action);
81 $self->_controller_actions($attr_value);
83 # trigger lazy builder
84 $self->_all_actions_attributes;
88 sub _build__action_roles {
90 my @roles = $self->_expand_role_shortname($self->_action_role_args);
91 load_class($_) for @roles;
95 sub _build__all_actions_attributes {
97 delete $self->_controller_actions->{'*'} || {};
102 Catalyst::Controller - Catalyst Controller base class
106 package MyApp::Controller::Search
107 use base qw/Catalyst::Controller/;
110 my ($self,$c,@args) = @_;
112 } # Dispatches to /search/foo
116 Controllers are where the actions in the Catalyst framework
117 reside. Each action is represented by a function with an attribute to
118 identify what kind of action it is. See the L<Catalyst::Dispatcher>
119 for more info about how Catalyst dispatches to actions.
123 #I think both of these could be attributes. doesn't really seem like they need
124 #to be class data. i think that attributes +default would work just fine
125 __PACKAGE__->mk_classdata($_) for qw/_dispatch_steps _action_class _action_role_prefix/;
127 __PACKAGE__->_dispatch_steps( [qw/_BEGIN _AUTO _ACTION/] );
128 __PACKAGE__->_action_class('Catalyst::Action');
129 __PACKAGE__->_action_role_prefix([ 'Catalyst::ActionRole::' ]);
132 sub _DISPATCH : Private {
133 my ( $self, $c ) = @_;
135 foreach my $disp ( @{ $self->_dispatch_steps } ) {
136 last unless $c->forward($disp);
142 sub _BEGIN : Private {
143 my ( $self, $c ) = @_;
144 my $begin = ( $c->get_actions( 'begin', $c->namespace ) )[-1];
145 return 1 unless $begin;
146 $begin->dispatch( $c );
147 #If there is an error, all bets off
148 if( @{ $c->error }) {
149 return !@{ $c->error };
151 return $c->state || 1;
155 sub _AUTO : Private {
156 my ( $self, $c ) = @_;
157 my @auto = $c->get_actions( 'auto', $c->namespace );
158 foreach my $auto (@auto) {
159 # We FORCE the auto action user to explicitly return
160 # true. We need to do this since there's some auto
161 # users (Catalyst::Authentication::Credential::HTTP) that
162 # actually do a detach instead.
164 $auto->dispatch( $c );
165 return 0 unless $c->state;
167 return $c->state || 1;
170 sub _ACTION : Private {
171 my ( $self, $c ) = @_;
173 && $c->action->can('execute')
174 && defined $c->req->action )
176 $c->action->dispatch( $c );
178 #If there is an error, all bets off
179 if( @{ $c->error }) {
180 return !@{ $c->error };
182 return $c->state || 1;
187 my ( $self, $c ) = @_;
188 my $end = ( $c->get_actions( 'end', $c->namespace ) )[-1];
189 return 1 unless $end;
190 $end->dispatch( $c );
191 return !@{ $c->error };
195 my ( $self, $name ) = @_;
196 my $app = ($self->isa('Catalyst') ? $self : $self->_application);
197 return $app->dispatcher->get_action($name, $self->action_namespace);
200 #my opinion is that this whole sub really should be a builder method, not
201 #something that happens on every call. Anyone else disagree?? -- groditi
202 ## -- apparently this is all just waiting for app/ctx split
203 around action_namespace => sub {
205 my ( $self, $c ) = @_;
207 my $class = ref($self) || $self;
208 my $appclass = ref($c) || $c;
210 return $self->$orig if $self->has_action_namespace;
212 return $class->config->{namespace} if exists $class->config->{namespace};
217 $case_s = $appclass->config->{case_sensitive};
219 if ($self->isa('Catalyst')) {
220 $case_s = $class->config->{case_sensitive};
223 $case_s = ref($self->_application)->config->{case_sensitive};
225 confess("Can't figure out case_sensitive setting");
230 my $namespace = Catalyst::Utils::class2prefix($self->catalyst_component_name, $case_s) || '';
231 $self->$orig($namespace) if ref($self);
235 #Once again, this is probably better written as a builder method
236 around path_prefix => sub {
240 return $self->$orig if $self->has_path_prefix;
242 return $self->config->{path} if exists $self->config->{path};
244 my $namespace = $self->action_namespace(@_);
245 $self->$orig($namespace) if ref($self);
249 sub get_action_methods {
251 my $meta = find_meta($self) || confess("No metaclass setup for $self");
253 sprintf "Metaclass %s for %s cannot support register_actions.",
254 ref $meta, $meta->name,
255 ) unless $meta->can('get_nearest_methods_with_attributes');
256 my @methods = $meta->get_nearest_methods_with_attributes;
258 # actions specified via config are also action_methods
262 $meta->find_method_by_name($_)
263 || confess( sprintf 'Action "%s" is not available from controller %s',
265 } keys %{ $self->_controller_actions }
267 return uniq @methods;
271 sub register_actions {
272 my ( $self, $c ) = @_;
273 $self->register_action_methods( $c, $self->get_action_methods );
276 sub register_action_methods {
277 my ( $self, $c, @methods ) = @_;
278 my $class = $self->catalyst_component_name;
279 #this is still not correct for some reason.
280 my $namespace = $self->action_namespace($c);
283 if (!blessed($self) && $self eq $c && scalar(@methods)) {
284 my @really_bad_methods = grep { ! /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/ } map { $_->name } @methods;
285 if (scalar(@really_bad_methods)) {
286 $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.");
290 foreach my $method (@methods) {
291 my $name = $method->name;
292 # Horrible hack! All method metaclasses should have an attributes
293 # method, core Moose bug - see r13354.
294 my $attributes = $method->can('attributes') ? $method->attributes : [];
295 my $attrs = $self->_parse_attrs( $c, $name, @{ $attributes } );
296 if ( $attrs->{Private} && ( keys %$attrs > 1 ) ) {
297 $c->log->warn( 'Bad action definition "'
298 . join( ' ', @{ $attributes } )
299 . qq/" for "$class->$name"/ )
303 my $reverse = $namespace ? "${namespace}/${name}" : $name;
304 my $action = $self->create_action(
306 code => $method->body,
308 namespace => $namespace,
310 attributes => $attrs,
313 $c->dispatcher->register( $c, $action );
317 sub _apply_action_class_roles {
318 my ($self, $class, @roles) = @_;
320 load_class($_) for @roles;
321 my $meta = Moose::Meta::Class->initialize($class)->create_anon_class(
322 superclasses => [$class],
326 $meta->add_method(meta => sub { $meta });
335 my $class = (exists $args{attributes}{ActionClass}
336 ? $args{attributes}{ActionClass}[0]
337 : $self->_action_class);
347 my $class = $self->action_class(%args);
350 Moose->init_meta(for_class => $class)
351 unless Class::MOP::does_metaclass_exist($class);
353 unless ($args{name} =~ /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/) {
354 my @roles = $self->gather_action_roles(%args);
355 push @roles, $self->gather_default_action_roles(%args);
357 $class = $self->_apply_action_class_roles($class, @roles) if @roles;
363 : $self->config->{action_args}
367 %{ $action_args->{'*'} || {} },
368 %{ $action_args->{ $args{name} } || {} },
371 return $class->new({ %extra_args, %args });
374 sub gather_action_roles {
375 my ($self, %args) = @_;
377 (blessed $self ? $self->_action_roles : ()),
378 @{ $args{attributes}->{Does} || [] },
382 sub gather_default_action_roles {
383 my ($self, %args) = @_;
385 push @roles, 'Catalyst::ActionRole::HTTPMethods'
386 if $args{attributes}->{Method};
388 push @roles, 'Catalyst::ActionRole::ConsumesContent'
389 if $args{attributes}->{Consumes};
391 push @roles, 'Catalyst::ActionRole::Scheme'
392 if $args{attributes}->{Scheme};
394 push @roles, 'Catalyst::ActionRole::QueryMatching'
395 if $args{attributes}->{Query};
400 my ( $self, $c, $name, @attrs ) = @_;
404 foreach my $attr (@attrs) {
406 # Parse out :Foo(bar) into Foo => bar etc (and arrayify)
408 if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.+?)?\s*\))?$/ ) )
411 if ( defined $value ) {
412 ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
414 push( @{ $raw_attributes{$key} }, $value );
418 my ($actions_config, $all_actions_config);
420 $actions_config = $self->_controller_actions;
421 # No, you're not getting actions => { '*' => ... } with actions in MyApp.
422 $all_actions_config = $self->_all_actions_attributes;
424 my $cfg = $self->config;
425 $actions_config = $self->merge_config_hashes($cfg->{actions}, $cfg->{action});
426 $all_actions_config = {};
431 # Note we deep copy array refs here to stop crapping on config
432 # when attributes are parsed. RT#65463
433 exists $actions_config->{$name} ? map { is_plain_arrayref($_) ? [ @$_ ] : $_ } %{ $actions_config->{$name } } : (),
436 # Private actions with additional attributes will raise a warning and then
437 # be ignored. Adding '*' arguments to the default _DISPATCH / etc. methods,
438 # which are Private, will prevent those from being registered. They should
439 # probably be turned into :Actions instead, or we might want to otherwise
440 # disambiguate between those built-in internal actions and user-level
442 %raw_attributes = (%{ $all_actions_config }, %raw_attributes)
443 unless $raw_attributes{Private};
445 my %final_attributes;
447 while (my ($key, $value) = each %raw_attributes){
448 my $new_attrs = $self->_parse_attr($c, $name, $key => $value );
449 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
452 return \%final_attributes;
456 my ($self, $c, $name, $key, $values) = @_;
458 my %final_attributes;
459 foreach my $value (is_plain_arrayref($values) ? @$values : $values) {
460 my $meth = "_parse_${key}_attr";
461 if ( my $code = $self->can($meth) ) {
462 my %new_attrs = $self->$code( $c, $name, $value );
463 while (my ($new_key, $value) = each %new_attrs){
464 my $new_attrs = $key eq $new_key ?
465 { $new_key => [$value] } :
466 $self->_parse_attr($c, $name, $new_key => $value );
467 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
471 push( @{ $final_attributes{$key} }, $value );
475 return \%final_attributes;
478 sub _parse_Global_attr {
479 my ( $self, $c, $name, $value ) = @_;
480 # _parse_attr will call _parse_Path_attr for us
481 return Path => "/$name";
484 sub _parse_Absolute_attr { shift->_parse_Global_attr(@_); }
486 sub _parse_Local_attr {
487 my ( $self, $c, $name, $value ) = @_;
488 # _parse_attr will call _parse_Path_attr for us
489 return Path => $name;
492 sub _parse_Relative_attr { shift->_parse_Local_attr(@_); }
494 sub _parse_Path_attr {
495 my ( $self, $c, $name, $value ) = @_;
496 $value = '' if !defined $value;
497 if ( $value =~ m!^/! ) {
498 return ( 'Path', $value );
500 elsif ( length $value ) {
501 return ( 'Path', join( '/', $self->path_prefix($c), $value ) );
504 return ( 'Path', $self->path_prefix($c) );
508 sub _parse_Chained_attr {
509 my ($self, $c, $name, $value) = @_;
511 if (defined($value) && length($value)) {
513 $value = '/'.$self->action_namespace($c);
514 } elsif (my ($rel, $rest) = $value =~ /^((?:\.{2}\/)+)(.*)$/) {
515 my @parts = split '/', $self->action_namespace($c);
516 my @levels = split '/', $rel;
518 $value = '/'.join('/', @parts[0 .. $#parts - @levels], $rest);
519 } elsif ($value !~ m/^\//) {
520 my $action_ns = $self->action_namespace($c);
523 $value = '/'.join('/', $action_ns, $value);
525 $value = '/'.$value; # special case namespace '' (root)
532 return Chained => $value;
535 sub _parse_ChainedParent_attr {
536 my ($self, $c, $name, $value) = @_;
537 return $self->_parse_Chained_attr($c, $name, '../'.$name);
540 sub _parse_PathPrefix_attr {
541 my ( $self, $c ) = @_;
542 return PathPart => $self->path_prefix($c);
545 sub _parse_ActionClass_attr {
546 my ( $self, $c, $name, $value ) = @_;
547 my $appname = $self->_application;
548 $value = Catalyst::Utils::resolve_namespace($appname . '::Action', $self->_action_class, $value);
549 return ( 'ActionClass', $value );
552 sub _parse_MyAction_attr {
553 my ( $self, $c, $name, $value ) = @_;
555 my $appclass = Catalyst::Utils::class2appclass($self);
556 $value = "+${appclass}::Action::${value}";
558 return ( 'ActionClass', $value );
561 sub _parse_Does_attr {
562 my ($self, $app, $name, $value) = @_;
563 return Does => $self->_expand_role_shortname($value);
566 sub _parse_GET_attr { Method => 'GET' }
567 sub _parse_POST_attr { Method => 'POST' }
568 sub _parse_PUT_attr { Method => 'PUT' }
569 sub _parse_DELETE_attr { Method => 'DELETE' }
570 sub _parse_OPTIONS_attr { Method => 'OPTIONS' }
571 sub _parse_HEAD_attr { Method => 'HEAD' }
572 sub _parse_PATCH_attr { Method => 'PATCH' }
574 sub _expand_role_shortname {
575 my ($self, @shortnames) = @_;
576 my $app = $self->_application;
578 my $prefix = $self->can('_action_role_prefix') ? $self->_action_role_prefix : ['Catalyst::ActionRole::'];
579 my @prefixes = (qq{${app}::ActionRole::}, @$prefix);
581 return String::RewritePrefix->rewrite(
583 my $loaded = load_first_existing_class(
584 map { "$_$_[0]" } @prefixes
586 return first { $loaded =~ /^$_/ }
587 sort { length $b <=> length $a } @prefixes;
595 __PACKAGE__->meta->make_immutable;
603 Like any other L<Catalyst::Component>, controllers have a config hash,
604 accessible through $self->config from the controller actions. Some
605 settings are in use by the Catalyst framework:
609 This specifies the internal namespace the controller should be bound
610 to. By default the controller is bound to the URI version of the
611 controller name. For instance controller 'MyApp::Controller::Foo::Bar'
612 will be bound to 'foo/bar'. The default Root controller is an example
613 of setting namespace to '' (the null string).
617 Sets 'path_prefix', as described below.
621 Allows you to set the attributes that the dispatcher creates actions out of.
622 This allows you to do 'rails style routes', or override some of the
623 attribute definitions of actions composed from Roles.
624 You can set arguments globally (for all actions of the controller) and
625 specifically (for a single action).
629 '*' => { Chained => 'base', Args => 0 },
630 base => { Chained => '/', PathPart => '', CaptureArgs => 0 },
634 In the case above every sub in the package would be made into a Chain
635 endpoint with a URI the same as the sub name for each sub, chained
636 to the sub named C<base>. Ergo dispatch to C</example> would call the
637 C<base> method, then the C<example> method.
641 Allows you to set constructor arguments on your actions. You can set arguments
642 globally and specifically (as above).
643 This is particularly useful when using C<ActionRole>s
644 (L<Catalyst::Controller::ActionRole>) and custom C<ActionClass>es.
648 '*' => { globalarg1 => 'hello', globalarg2 => 'goodbye' },
649 'specific_action' => { customarg => 'arg1' },
653 In the case above the action class associated with C<specific_action> would get
654 passed the following arguments, in addition to the normal action constructor
655 arguments, when it is instantiated:
657 (globalarg1 => 'hello', globalarg2 => 'goodbye', customarg => 'arg1')
661 =head2 BUILDARGS ($app, @args)
663 From L<Catalyst::Component::ApplicationAttribute>, stashes the application
664 instance as $self->_application.
666 =head2 $self->action_for($action_name)
668 Returns the Catalyst::Action object (if any) for a given action in this
669 controller or relative to it. You may refer to actions in controllers
670 nested under the current controllers namespace, or in controllers 'up'
671 from the current controller namespace. For example:
673 package MyApp::Controller::One::Two;
674 use base 'Catalyst::Controller';
678 $self->action_for('foo'); # action 'foo' in Controller 'One::Two'
679 $self->action_for('three/bar'); # action 'bar' in Controller 'One::Two::Three'
680 $self->action_for('../boo'); # action 'boo' in Controller 'One'
683 This returns 'undef' if there is no action matching the requested action
684 name (after any path normalization) so you should check for this as needed.
686 =head2 $self->action_namespace($c)
688 Returns the private namespace for actions in this component. Defaults
689 to a value from the controller name (for
690 e.g. MyApp::Controller::Foo::Bar becomes "foo/bar") or can be
691 overridden from the "namespace" config key.
694 =head2 $self->path_prefix($c)
696 Returns the default path prefix for :PathPrefix, :Local and
697 relative :Path actions in this component. Defaults to the action_namespace or
698 can be overridden from the "path" config key.
700 =head2 $self->register_actions($c)
702 Finds all applicable actions for this component, creates
703 Catalyst::Action objects (using $self->create_action) for them and
704 registers them with $c->dispatcher.
706 =head2 $self->get_action_methods()
708 Returns a list of L<Moose::Meta::Method> objects, doing the
709 L<MooseX::MethodAttributes::Role::Meta::Method> role, which are the set of
710 action methods for this package.
712 =head2 $self->register_action_methods($c, @methods)
714 Creates action objects for a set of action methods using C< create_action >,
715 and registers them with the dispatcher.
717 =head2 $self->action_class(%args)
719 Used when a controller is creating an action to determine the correct base
722 =head2 $self->create_action(%args)
724 Called with a hash of data to be use for construction of a new
725 Catalyst::Action (or appropriate sub/alternative class) object.
727 =head2 $self->gather_action_roles(\%action_args)
729 Gathers the list of roles to apply to an action with the given %action_args.
731 =head2 $self->gather_default_action_roles(\%action_args)
733 returns a list of action roles to be applied based on core, builtin rules.
734 Currently only the L<Catalyst::ActionRole::HTTPMethods> role is applied
737 =head2 $self->_application
741 Returns the application instance stored by C<new()>
743 =head1 ACTION SUBROUTINE ATTRIBUTES
745 Please see L<Catalyst::Manual::Intro> for more details
747 Think of action attributes as a sort of way to record metadata about an action,
748 similar to how annotations work in other languages you might have heard of.
749 Generally L<Catalyst> uses these to influence how the dispatcher sees your
750 action and when it will run it in response to an incoming request. They can
751 also be used for other things. Here's a summary, but you should refer to the
752 linked manual page for additional help.
756 sub homepage :Global { ... }
758 A global action defined in any controller always runs relative to your root.
759 So the above is the same as:
761 sub myaction :Path("/homepage") { ... }
765 Status: Deprecated alias to L</Global>.
769 Alias to "Path("$action_name"). The following two actions are the same:
771 sub myaction :Local { ... }
772 sub myaction :Path('myaction') { ... }
776 Status: Deprecated alias to L</Local>
780 Handle various types of paths:
782 package MyApp::Controller::Baz {
786 sub myaction1 :Path { ... } # -> /baz
787 sub myaction2 :Path('foo') { ... } # -> /baz/foo
788 sub myaction2 :Path('/bar') { ... } # -> /bar
791 This is a general toolbox for attaching your action to a given path.
798 B<Status: Deprecated.> Use Chained methods or other techniques.
799 If you really depend on this, install the standalone
800 L<Catalyst::DispatchType::Regex> distribution.
802 A global way to match a give regular expression in the incoming request path.
808 B<Status: Deprecated.> Use Chained methods or other techniques.
809 If you really depend on this, install the standalone
810 L<Catalyst::DispatchType::Regex> distribution.
812 Like L</Regex> but scoped under the namespace of the containing controller
824 Allowed values for CaptureArgs is a single integer (CaptureArgs(2), meaning two
825 allowed) or you can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny>
826 named constraint such as CaptureArgs(Int,Str) would require two args with
827 the first being a Integer and the second a string. You may declare your own
828 custom type constraints and import them into the controller namespace:
830 package MyApp::Controller::Root;
833 use MooseX::MethodAttributes;
834 use MyApp::Types qw/Int/;
836 extends 'Catalyst::Controller';
838 sub chain_base :Chained(/) CaptureArgs(1) { }
840 sub any_priority_chain :Chained(chain_base) PathPart('') Args(1) { }
842 sub int_priority_chain :Chained(chain_base) PathPart('') Args(Int) { }
844 See L<Catalyst::RouteMatching> for more.
846 Please see L<Catalyst::DispatchType::Chained> for more.
850 Set the base class for the action, defaults to L</Catalyst::Action>. It is now
851 preferred to use L</Does>.
855 Set the ActionClass using a custom Action in your project namespace.
857 The following is exactly the same:
859 sub foo_action1 : Local ActionClass('+MyApp::Action::Bar') { ... }
860 sub foo_action2 : Local MyAction('Bar') { ... }
864 package MyApp::Controller::Zoo;
866 sub foo : Local Does('Moo') { ... } # Catalyst::ActionRole::
867 sub bar : Local Does('~Moo') { ... } # MyApp::ActionRole::Moo
868 sub baz : Local Does('+MyApp::ActionRole::Moo') { ... }
886 Sets the give action path to match the specified HTTP method, or via one of the
887 broadly accepted methods of overriding the 'true' method (see
888 L<Catalyst::ActionRole::HTTPMethods>).
892 When used with L</Path> indicates the number of arguments expected in
893 the path. However if no Args value is set, assumed to 'slurp' all
894 remaining path pars under this namespace.
896 Allowed values for Args is a single integer (Args(2), meaning two allowed) or you
897 can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny> named constraint such
898 as Args(Int,Str) would require two args with the first being a Integer and the
899 second a string. You may declare your own custom type constraints and import
900 them into the controller namespace:
902 package MyApp::Controller::Root;
905 use MooseX::MethodAttributes;
906 use MyApp::Types qw/Tuple Int Str StrMatch UserId/;
908 extends 'Catalyst::Controller';
910 sub user :Local Args(UserId) {
911 my ($self, $c, $int) = @_;
914 sub an_int :Local Args(Int) {
915 my ($self, $c, $int) = @_;
918 sub many_ints :Local Args(ArrayRef[Int]) {
919 my ($self, $c, @ints) = @_;
922 sub match :Local Args(StrMatch[qr{\d\d-\d\d-\d\d}]) {
923 my ($self, $c, $int) = @_;
926 If you choose not to use imported type constraints (like L<Type::Tiny>, or <MooseX::Types>
927 you may use L<Moose> 'stringy' types however just like when you use these types in your
928 declared attributes you must quote them:
930 sub my_moose_type :Local Args('Int') { ... }
932 If you use 'reference' type constraints (such as ArrayRef[Int]) that have an unknown
933 number of allowed matches, we set this the same way "Args" is. Please keep in mind
934 that actions with an undetermined number of args match at lower precedence than those
935 with a fixed number. You may use reference types such as Tuple from L<Types::Standard>
936 that allows you to fix the number of allowed args. For example Args(Tuple[Int,Int])
937 would be determined to be two args (or really the same as Args(Int,Int).) You may
938 find this useful for creating custom subtypes with complex matching rules that you
939 wish to reuse over many actions.
941 See L<Catalyst::RouteMatching> for more.
943 B<Note>: It is highly recommended to use L<Type::Tiny> for your type constraints over
944 other options. L<Type::Tiny> exposed a better meta data interface which allows us to
945 do more and better types of introspection driving tests and debugging.
947 =head2 Consumes('...')
949 Matches the current action against the content-type of the request. Typically
950 this is used when the request is a POST or PUT and you want to restrict the
951 submitted content type. For example, you might have an HTML for that either
952 returns classic url encoded form data, or JSON when Javascript is enabled. In
953 this case you may wish to match either incoming type to one of two different
954 actions, for properly processing.
958 sub is_json : Chained('start') Consumes('application/json') { ... }
959 sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
960 sub is_multipart : Chained('start') Consumes('multipart/form-data') { ... }
962 To reduce boilerplate, we include the following content type shortcuts:
966 sub is_json : Chained('start') Consume(JSON) { ... }
967 sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
968 sub is_multipart : Chained('start') Consumes(Multipart) { ... }
970 You may specify more than one match:
974 : Consumes('application/x-www-form-urlencoded')
975 : Consumes('multipart/form-data')
979 : Consumes(UrlEncoded)
980 : Consumes(Multipart)
982 Since it is a common case the shortcut C<HTMLForm> matches both
983 'application/x-www-form-urlencoded' and 'multipart/form-data'. Here's the full
984 list of available shortcuts:
986 JSON => 'application/json',
987 JS => 'application/javascript',
988 PERL => 'application/perl',
991 Plain => 'text/plain',
992 UrlEncoded => 'application/x-www-form-urlencoded',
993 Multipart => 'multipart/form-data',
994 HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
996 Please keep in mind that when dispatching, L<Catalyst> will match the first most
997 relevant case, so if you use the C<Consumes> attribute, you should place your
998 most accurate matches early in the Chain, and your 'catchall' actions last.
1000 See L<Catalyst::ActionRole::ConsumesContent> for more.
1004 Allows you to specify a URI scheme for the action or action chain. For example
1005 you can required that a given path be C<https> or that it is a websocket endpoint
1006 C<ws> or C<wss>. For an action chain you may currently only have one defined
1009 package MyApp::Controller::Root;
1011 use base 'Catalyst::Controller';
1013 sub is_http :Path(scheme) Scheme(http) Args(0) {
1014 my ($self, $c) = @_;
1015 $c->response->body("is_http");
1018 sub is_https :Path(scheme) Scheme(https) Args(0) {
1019 my ($self, $c) = @_;
1020 $c->response->body("is_https");
1023 In the above example http://localhost/root/scheme would match the first
1024 action (is_http) but https://localhost/root/scheme would match the second.
1026 As an added benefit, if an action or action chain defines a Scheme, when using
1027 $c->uri_for the scheme of the generated URL will use what you define in the action
1028 or action chain (the current behavior is to set the scheme based on the current
1029 incoming request). This makes it easier to use uri_for on websites where some
1030 paths are secure and others are not. You may also use this to other schemes
1033 See L<Catalyst::ActionRole::Scheme> for more.
1035 =head1 OPTIONAL METHODS
1037 =head2 _parse_[$name]_attr
1039 Allows you to customize parsing of subroutine attributes.
1041 sub myaction1 :Path TwoArgs { ... }
1043 sub _parse_TwoArgs_attr {
1044 my ( $self, $c, $name, $value ) = @_;
1045 # $self -> controller instance
1050 Please note that this feature does not let you actually assign new functions
1051 to actions via subroutine attributes, but is really more for creating useful
1052 aliases to existing core and extended attributes, and transforms based on
1053 existing information (like from configuration). Code for actually doing
1054 something meaningful with the subroutine attributes will be located in the
1055 L<Catalyst::Action> classes (or your subclasses), L<Catalyst::Dispatcher> and
1056 in subclasses of L<Catalyst::DispatchType>. Remember these methods only get
1057 called basically once when the application is starting, not per request!
1061 Catalyst Contributors, see Catalyst.pm
1065 This library is free software. You can redistribute it and/or modify
1066 it under the same terms as Perl itself.