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 namespace::clean -except => 'meta';
13 extends qw/Catalyst::Component/;
14 with qw/MooseX::MethodAttributes::Role::AttrContainer::Inheritable/;
17 use MooseX::MethodAttributes;
18 use Catalyst::Exception;
21 with 'Catalyst::Component::ApplicationAttribute';
27 predicate => 'has_path_prefix',
30 has action_namespace => (
33 init_arg => 'namespace',
34 predicate => 'has_action_namespace',
38 accessor => '_controller_actions',
43 has _action_role_args => (
44 traits => [qw(Array)],
45 isa => 'ArrayRef[Str]',
46 init_arg => 'action_roles',
47 default => sub { [] },
49 _action_role_args => 'elements',
53 has _action_roles => (
54 traits => [qw(Array)],
55 isa => 'ArrayRef[RoleName]',
58 builder => '_build__action_roles',
60 _action_roles => 'elements',
64 has action_args => (is => 'ro');
66 # ->config(actions => { '*' => ...
67 has _all_actions_attributes => (
72 builder => '_build__all_actions_attributes',
76 my ($self, $args) = @_;
77 my $action = delete $args->{action} || {};
78 my $actions = delete $args->{actions} || {};
79 my $attr_value = $self->merge_config_hashes($actions, $action);
80 $self->_controller_actions($attr_value);
82 # trigger lazy builder
83 $self->_all_actions_attributes;
87 sub _build__action_roles {
89 my @roles = $self->_expand_role_shortname($self->_action_role_args);
90 load_class($_) for @roles;
94 sub _build__all_actions_attributes {
96 delete $self->_controller_actions->{'*'} || {};
101 Catalyst::Controller - Catalyst Controller base class
105 package MyApp::Controller::Search
106 use base qw/Catalyst::Controller/;
109 my ($self,$c,@args) = @_;
111 } # Dispatches to /search/foo
115 Controllers are where the actions in the Catalyst framework
116 reside. Each action is represented by a function with an attribute to
117 identify what kind of action it is. See the L<Catalyst::Dispatcher>
118 for more info about how Catalyst dispatches to actions.
122 #I think both of these could be attributes. doesn't really seem like they need
123 #to be class data. i think that attributes +default would work just fine
124 __PACKAGE__->mk_classdata($_) for qw/_dispatch_steps _action_class _action_role_prefix/;
126 __PACKAGE__->_dispatch_steps( [qw/_BEGIN _AUTO _ACTION/] );
127 __PACKAGE__->_action_class('Catalyst::Action');
128 __PACKAGE__->_action_role_prefix([ 'Catalyst::ActionRole::' ]);
131 sub _DISPATCH : Private {
132 my ( $self, $c ) = @_;
134 foreach my $disp ( @{ $self->_dispatch_steps } ) {
135 last unless $c->forward($disp);
141 sub _BEGIN : Private {
142 my ( $self, $c ) = @_;
143 my $begin = ( $c->get_actions( 'begin', $c->namespace ) )[-1];
144 return 1 unless $begin;
145 $begin->dispatch( $c );
146 #If there is an error, all bets off
147 if( @{ $c->error }) {
148 return !@{ $c->error };
150 return $c->state || 1;
154 sub _AUTO : Private {
155 my ( $self, $c ) = @_;
156 my @auto = $c->get_actions( 'auto', $c->namespace );
157 foreach my $auto (@auto) {
158 # We FORCE the auto action user to explicitly return
159 # true. We need to do this since there's some auto
160 # users (Catalyst::Authentication::Credential::HTTP) that
161 # actually do a detach instead.
163 $auto->dispatch( $c );
164 return 0 unless $c->state;
166 return $c->state || 1;
169 sub _ACTION : Private {
170 my ( $self, $c ) = @_;
172 && $c->action->can('execute')
173 && defined $c->req->action )
175 $c->action->dispatch( $c );
177 #If there is an error, all bets off
178 if( @{ $c->error }) {
179 return !@{ $c->error };
181 return $c->state || 1;
186 my ( $self, $c ) = @_;
187 my $end = ( $c->get_actions( 'end', $c->namespace ) )[-1];
188 return 1 unless $end;
189 $end->dispatch( $c );
190 return !@{ $c->error };
194 my ( $self, $name ) = @_;
195 my $app = ($self->isa('Catalyst') ? $self : $self->_application);
196 return $app->dispatcher->get_action($name, $self->action_namespace);
199 #my opinion is that this whole sub really should be a builder method, not
200 #something that happens on every call. Anyone else disagree?? -- groditi
201 ## -- apparently this is all just waiting for app/ctx split
202 around action_namespace => sub {
204 my ( $self, $c ) = @_;
206 my $class = ref($self) || $self;
207 my $appclass = ref($c) || $c;
209 return $self->$orig if $self->has_action_namespace;
211 return $class->config->{namespace} if exists $class->config->{namespace};
216 $case_s = $appclass->config->{case_sensitive};
218 if ($self->isa('Catalyst')) {
219 $case_s = $class->config->{case_sensitive};
222 $case_s = ref($self->_application)->config->{case_sensitive};
224 confess("Can't figure out case_sensitive setting");
229 my $namespace = Catalyst::Utils::class2prefix($self->catalyst_component_name, $case_s) || '';
230 $self->$orig($namespace) if ref($self);
234 #Once again, this is probably better written as a builder method
235 around path_prefix => sub {
239 return $self->$orig if $self->has_path_prefix;
241 return $self->config->{path} if exists $self->config->{path};
243 my $namespace = $self->action_namespace(@_);
244 $self->$orig($namespace) if ref($self);
248 sub get_action_methods {
250 my $meta = find_meta($self) || confess("No metaclass setup for $self");
252 sprintf "Metaclass %s for %s cannot support register_actions.",
253 ref $meta, $meta->name,
254 ) unless $meta->can('get_nearest_methods_with_attributes');
255 my @methods = $meta->get_nearest_methods_with_attributes;
257 # actions specified via config are also action_methods
261 $meta->find_method_by_name($_)
262 || confess( sprintf 'Action "%s" is not available from controller %s',
264 } keys %{ $self->_controller_actions }
266 return uniq @methods;
270 sub register_actions {
271 my ( $self, $c ) = @_;
272 $self->register_action_methods( $c, $self->get_action_methods );
275 sub register_action_methods {
276 my ( $self, $c, @methods ) = @_;
277 my $class = $self->catalyst_component_name;
278 #this is still not correct for some reason.
279 my $namespace = $self->action_namespace($c);
282 if (!blessed($self) && $self eq $c && scalar(@methods)) {
283 my @really_bad_methods = grep { ! /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/ } map { $_->name } @methods;
284 if (scalar(@really_bad_methods)) {
285 $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.");
289 foreach my $method (@methods) {
290 my $name = $method->name;
291 # Horrible hack! All method metaclasses should have an attributes
292 # method, core Moose bug - see r13354.
293 my $attributes = $method->can('attributes') ? $method->attributes : [];
294 my $attrs = $self->_parse_attrs( $c, $name, @{ $attributes } );
295 if ( $attrs->{Private} && ( keys %$attrs > 1 ) ) {
296 $c->log->warn( 'Bad action definition "'
297 . join( ' ', @{ $attributes } )
298 . qq/" for "$class->$name"/ )
302 my $reverse = $namespace ? "${namespace}/${name}" : $name;
303 my $action = $self->create_action(
305 code => $method->body,
307 namespace => $namespace,
309 attributes => $attrs,
312 $c->dispatcher->register( $c, $action );
316 sub _apply_action_class_roles {
317 my ($self, $class, @roles) = @_;
319 load_class($_) for @roles;
320 my $meta = Moose::Meta::Class->initialize($class)->create_anon_class(
321 superclasses => [$class],
325 $meta->add_method(meta => sub { $meta });
334 my $class = (exists $args{attributes}{ActionClass}
335 ? $args{attributes}{ActionClass}[0]
336 : $self->_action_class);
346 my $class = $self->action_class(%args);
349 Moose->init_meta(for_class => $class)
350 unless Class::MOP::does_metaclass_exist($class);
352 unless ($args{name} =~ /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/) {
353 my @roles = $self->gather_action_roles(%args);
354 push @roles, $self->gather_default_action_roles(%args);
356 $class = $self->_apply_action_class_roles($class, @roles) if @roles;
362 : $self->config->{action_args}
366 %{ $action_args->{'*'} || {} },
367 %{ $action_args->{ $args{name} } || {} },
370 return $class->new({ %extra_args, %args });
373 sub gather_action_roles {
374 my ($self, %args) = @_;
376 (blessed $self ? $self->_action_roles : ()),
377 @{ $args{attributes}->{Does} || [] },
381 sub gather_default_action_roles {
382 my ($self, %args) = @_;
384 push @roles, 'Catalyst::ActionRole::HTTPMethods'
385 if $args{attributes}->{Method};
387 push @roles, 'Catalyst::ActionRole::ConsumesContent'
388 if $args{attributes}->{Consumes};
390 push @roles, 'Catalyst::ActionRole::Scheme'
391 if $args{attributes}->{Scheme};
393 push @roles, 'Catalyst::ActionRole::QueryMatching'
394 if $args{attributes}->{Query};
399 my ( $self, $c, $name, @attrs ) = @_;
403 foreach my $attr (@attrs) {
405 # Parse out :Foo(bar) into Foo => bar etc (and arrayify)
407 if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.+?)?\s*\))?$/ ) )
410 if ( defined $value ) {
411 ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
413 push( @{ $raw_attributes{$key} }, $value );
417 my ($actions_config, $all_actions_config);
419 $actions_config = $self->_controller_actions;
420 # No, you're not getting actions => { '*' => ... } with actions in MyApp.
421 $all_actions_config = $self->_all_actions_attributes;
423 my $cfg = $self->config;
424 $actions_config = $self->merge_config_hashes($cfg->{actions}, $cfg->{action});
425 $all_actions_config = {};
430 # Note we deep copy array refs here to stop crapping on config
431 # when attributes are parsed. RT#65463
432 exists $actions_config->{$name} ? map { ref($_) eq 'ARRAY' ? [ @$_ ] : $_ } %{ $actions_config->{$name } } : (),
435 # Private actions with additional attributes will raise a warning and then
436 # be ignored. Adding '*' arguments to the default _DISPATCH / etc. methods,
437 # which are Private, will prevent those from being registered. They should
438 # probably be turned into :Actions instead, or we might want to otherwise
439 # disambiguate between those built-in internal actions and user-level
441 %raw_attributes = (%{ $all_actions_config }, %raw_attributes)
442 unless $raw_attributes{Private};
444 my %final_attributes;
446 while (my ($key, $value) = each %raw_attributes){
447 my $new_attrs = $self->_parse_attr($c, $name, $key => $value );
448 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
451 return \%final_attributes;
455 my ($self, $c, $name, $key, $values) = @_;
457 my %final_attributes;
458 foreach my $value (ref($values) eq 'ARRAY' ? @$values : $values) {
459 my $meth = "_parse_${key}_attr";
460 if ( my $code = $self->can($meth) ) {
461 my %new_attrs = $self->$code( $c, $name, $value );
462 while (my ($new_key, $value) = each %new_attrs){
463 my $new_attrs = $key eq $new_key ?
464 { $new_key => [$value] } :
465 $self->_parse_attr($c, $name, $new_key => $value );
466 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
470 push( @{ $final_attributes{$key} }, $value );
474 return \%final_attributes;
477 sub _parse_Global_attr {
478 my ( $self, $c, $name, $value ) = @_;
479 # _parse_attr will call _parse_Path_attr for us
480 return Path => "/$name";
483 sub _parse_Absolute_attr { shift->_parse_Global_attr(@_); }
485 sub _parse_Local_attr {
486 my ( $self, $c, $name, $value ) = @_;
487 # _parse_attr will call _parse_Path_attr for us
488 return Path => $name;
491 sub _parse_Relative_attr { shift->_parse_Local_attr(@_); }
493 sub _parse_Path_attr {
494 my ( $self, $c, $name, $value ) = @_;
495 $value = '' if !defined $value;
496 if ( $value =~ m!^/! ) {
497 return ( 'Path', $value );
499 elsif ( length $value ) {
500 return ( 'Path', join( '/', $self->path_prefix($c), $value ) );
503 return ( 'Path', $self->path_prefix($c) );
507 sub _parse_Chained_attr {
508 my ($self, $c, $name, $value) = @_;
510 if (defined($value) && length($value)) {
512 $value = '/'.$self->action_namespace($c);
513 } elsif (my ($rel, $rest) = $value =~ /^((?:\.{2}\/)+)(.*)$/) {
514 my @parts = split '/', $self->action_namespace($c);
515 my @levels = split '/', $rel;
517 $value = '/'.join('/', @parts[0 .. $#parts - @levels], $rest);
518 } elsif ($value !~ m/^\//) {
519 my $action_ns = $self->action_namespace($c);
522 $value = '/'.join('/', $action_ns, $value);
524 $value = '/'.$value; # special case namespace '' (root)
531 return Chained => $value;
534 sub _parse_ChainedParent_attr {
535 my ($self, $c, $name, $value) = @_;
536 return $self->_parse_Chained_attr($c, $name, '../'.$name);
539 sub _parse_PathPrefix_attr {
540 my ( $self, $c ) = @_;
541 return PathPart => $self->path_prefix($c);
544 sub _parse_ActionClass_attr {
545 my ( $self, $c, $name, $value ) = @_;
546 my $appname = $self->_application;
547 $value = Catalyst::Utils::resolve_namespace($appname . '::Action', $self->_action_class, $value);
548 return ( 'ActionClass', $value );
551 sub _parse_MyAction_attr {
552 my ( $self, $c, $name, $value ) = @_;
554 my $appclass = Catalyst::Utils::class2appclass($self);
555 $value = "+${appclass}::Action::${value}";
557 return ( 'ActionClass', $value );
560 sub _parse_Does_attr {
561 my ($self, $app, $name, $value) = @_;
562 return Does => $self->_expand_role_shortname($value);
565 sub _parse_GET_attr { Method => 'GET' }
566 sub _parse_POST_attr { Method => 'POST' }
567 sub _parse_PUT_attr { Method => 'PUT' }
568 sub _parse_DELETE_attr { Method => 'DELETE' }
569 sub _parse_OPTIONS_attr { Method => 'OPTIONS' }
570 sub _parse_HEAD_attr { Method => 'HEAD' }
571 sub _parse_PATCH_attr { Method => 'PATCH' }
573 sub _expand_role_shortname {
574 my ($self, @shortnames) = @_;
575 my $app = $self->_application;
577 my $prefix = $self->can('_action_role_prefix') ? $self->_action_role_prefix : ['Catalyst::ActionRole::'];
578 my @prefixes = (qq{${app}::ActionRole::}, @$prefix);
580 return String::RewritePrefix->rewrite(
582 my $loaded = load_first_existing_class(
583 map { "$_$_[0]" } @prefixes
585 return first { $loaded =~ /^$_/ }
586 sort { length $b <=> length $a } @prefixes;
594 __PACKAGE__->meta->make_immutable;
602 Like any other L<Catalyst::Component>, controllers have a config hash,
603 accessible through $self->config from the controller actions. Some
604 settings are in use by the Catalyst framework:
608 This specifies the internal namespace the controller should be bound
609 to. By default the controller is bound to the URI version of the
610 controller name. For instance controller 'MyApp::Controller::Foo::Bar'
611 will be bound to 'foo/bar'. The default Root controller is an example
612 of setting namespace to '' (the null string).
616 Sets 'path_prefix', as described below.
620 Allows you to set the attributes that the dispatcher creates actions out of.
621 This allows you to do 'rails style routes', or override some of the
622 attribute definitions of actions composed from Roles.
623 You can set arguments globally (for all actions of the controller) and
624 specifically (for a single action).
628 '*' => { Chained => 'base', Args => 0 },
629 base => { Chained => '/', PathPart => '', CaptureArgs => 0 },
633 In the case above every sub in the package would be made into a Chain
634 endpoint with a URI the same as the sub name for each sub, chained
635 to the sub named C<base>. Ergo dispatch to C</example> would call the
636 C<base> method, then the C<example> method.
640 Allows you to set constructor arguments on your actions. You can set arguments
641 globally and specifically (as above).
642 This is particularly useful when using C<ActionRole>s
643 (L<Catalyst::Controller::ActionRole>) and custom C<ActionClass>es.
647 '*' => { globalarg1 => 'hello', globalarg2 => 'goodbye' },
648 'specific_action' => { customarg => 'arg1' },
652 In the case above the action class associated with C<specific_action> would get
653 passed the following arguments, in addition to the normal action constructor
654 arguments, when it is instantiated:
656 (globalarg1 => 'hello', globalarg2 => 'goodbye', customarg => 'arg1')
660 =head2 BUILDARGS ($app, @args)
662 From L<Catalyst::Component::ApplicationAttribute>, stashes the application
663 instance as $self->_application.
665 =head2 $self->action_for($action_name)
667 Returns the Catalyst::Action object (if any) for a given action in this
668 controller or relative to it. You may refer to actions in controllers
669 nested under the current controllers namespace, or in controllers 'up'
670 from the current controller namespace. For example:
672 package MyApp::Controller::One::Two;
673 use base 'Catalyst::Controller';
677 $self->action_for('foo'); # action 'foo' in Controller 'One::Two'
678 $self->action_for('three/bar'); # action 'bar' in Controller 'One::Two::Three'
679 $self->action_for('../boo'); # action 'boo' in Controller 'One'
682 This returns 'undef' if there is no action matching the requested action
683 name (after any path normalization) so you should check for this as needed.
685 =head2 $self->action_namespace($c)
687 Returns the private namespace for actions in this component. Defaults
688 to a value from the controller name (for
689 e.g. MyApp::Controller::Foo::Bar becomes "foo/bar") or can be
690 overridden from the "namespace" config key.
693 =head2 $self->path_prefix($c)
695 Returns the default path prefix for :PathPrefix, :Local and
696 relative :Path actions in this component. Defaults to the action_namespace or
697 can be overridden from the "path" config key.
699 =head2 $self->register_actions($c)
701 Finds all applicable actions for this component, creates
702 Catalyst::Action objects (using $self->create_action) for them and
703 registers them with $c->dispatcher.
705 =head2 $self->get_action_methods()
707 Returns a list of L<Moose::Meta::Method> objects, doing the
708 L<MooseX::MethodAttributes::Role::Meta::Method> role, which are the set of
709 action methods for this package.
711 =head2 $self->register_action_methods($c, @methods)
713 Creates action objects for a set of action methods using C< create_action >,
714 and registers them with the dispatcher.
716 =head2 $self->action_class(%args)
718 Used when a controller is creating an action to determine the correct base
721 =head2 $self->create_action(%args)
723 Called with a hash of data to be use for construction of a new
724 Catalyst::Action (or appropriate sub/alternative class) object.
726 =head2 $self->gather_action_roles(\%action_args)
728 Gathers the list of roles to apply to an action with the given %action_args.
730 =head2 $self->gather_default_action_roles(\%action_args)
732 returns a list of action roles to be applied based on core, builtin rules.
733 Currently only the L<Catalyst::ActionRole::HTTPMethods> role is applied
736 =head2 $self->_application
740 Returns the application instance stored by C<new()>
742 =head1 ACTION SUBROUTINE ATTRIBUTES
744 Please see L<Catalyst::Manual::Intro> for more details
746 Think of action attributes as a sort of way to record metadata about an action,
747 similar to how annotations work in other languages you might have heard of.
748 Generally L<Catalyst> uses these to influence how the dispatcher sees your
749 action and when it will run it in response to an incoming request. They can
750 also be used for other things. Here's a summary, but you should refer to the
751 linked manual page for additional help.
755 sub homepage :Global { ... }
757 A global action defined in any controller always runs relative to your root.
758 So the above is the same as:
760 sub myaction :Path("/homepage") { ... }
764 Status: Deprecated alias to L</Global>.
768 Alias to "Path("$action_name"). The following two actions are the same:
770 sub myaction :Local { ... }
771 sub myaction :Path('myaction') { ... }
775 Status: Deprecated alias to L</Local>
779 Handle various types of paths:
781 package MyApp::Controller::Baz {
785 sub myaction1 :Path { ... } # -> /baz
786 sub myaction2 :Path('foo') { ... } # -> /baz/foo
787 sub myaction2 :Path('/bar') { ... } # -> /bar
790 This is a general toolbox for attaching your action to a given path.
797 B<Status: Deprecated.> Use Chained methods or other techniques.
798 If you really depend on this, install the standalone
799 L<Catalyst::DispatchType::Regex> distribution.
801 A global way to match a give regular expression in the incoming request path.
807 B<Status: Deprecated.> Use Chained methods or other techniques.
808 If you really depend on this, install the standalone
809 L<Catalyst::DispatchType::Regex> distribution.
811 Like L</Regex> but scoped under the namespace of the containing controller
823 Allowed values for CaptureArgs is a single integer (CaptureArgs(2), meaning two
824 allowed) or you can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny>
825 named constraint such as CaptureArgs(Int,Str) would require two args with
826 the first being a Integer and the second a string. You may declare your own
827 custom type constraints and import them into the controller namespace:
829 package MyApp::Controller::Root;
832 use MooseX::MethodAttributes;
833 use MyApp::Types qw/Int/;
835 extends 'Catalyst::Controller';
837 sub chain_base :Chained(/) CaptureArgs(1) { }
839 sub any_priority_chain :Chained(chain_base) PathPart('') Args(1) { }
841 sub int_priority_chain :Chained(chain_base) PathPart('') Args(Int) { }
843 See L<Catalyst::RouteMatching> for more.
845 Please see L<Catalyst::DispatchType::Chained> for more.
849 Set the base class for the action, defaults to L</Catalyst::Action>. It is now
850 preferred to use L</Does>.
854 Set the ActionClass using a custom Action in your project namespace.
856 The following is exactly the same:
858 sub foo_action1 : Local ActionClass('+MyApp::Action::Bar') { ... }
859 sub foo_action2 : Local MyAction('Bar') { ... }
863 package MyApp::Controller::Zoo;
865 sub foo : Local Does('Moo') { ... } # Catalyst::ActionRole::
866 sub bar : Local Does('~Moo') { ... } # MyApp::ActionRole::Moo
867 sub baz : Local Does('+MyApp::ActionRole::Moo') { ... }
885 Sets the give action path to match the specified HTTP method, or via one of the
886 broadly accepted methods of overriding the 'true' method (see
887 L<Catalyst::ActionRole::HTTPMethods>).
891 When used with L</Path> indicates the number of arguments expected in
892 the path. However if no Args value is set, assumed to 'slurp' all
893 remaining path pars under this namespace.
895 Allowed values for Args is a single integer (Args(2), meaning two allowed) or you
896 can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny> named constraint such
897 as Args(Int,Str) would require two args with the first being a Integer and the
898 second a string. You may declare your own custom type constraints and import
899 them into the controller namespace:
901 package MyApp::Controller::Root;
904 use MooseX::MethodAttributes;
905 use MyApp::Types qw/Tuple Int Str StrMatch UserId/;
907 extends 'Catalyst::Controller';
909 sub user :Local Args(UserId) {
910 my ($self, $c, $int) = @_;
913 sub an_int :Local Args(Int) {
914 my ($self, $c, $int) = @_;
917 sub many_ints :Local Args(ArrayRef[Int]) {
918 my ($self, $c, @ints) = @_;
921 sub match :Local Args(StrMatch[qr{\d\d-\d\d-\d\d}]) {
922 my ($self, $c, $int) = @_;
925 If you choose not to use imported type constraints (like L<Type::Tiny>, or <MooseX::Types>
926 you may use L<Moose> 'stringy' types however just like when you use these types in your
927 declared attributes you must quote them:
929 sub my_moose_type :Local Args('Int') { ... }
931 If you use 'reference' type constraints (such as ArrayRef[Int]) that have an unknown
932 number of allowed matches, we set this the same way "Args" is. Please keep in mind
933 that actions with an undetermined number of args match at lower precedence than those
934 with a fixed number. You may use reference types such as Tuple from L<Types::Standard>
935 that allows you to fix the number of allowed args. For example Args(Tuple[Int,Int])
936 would be determined to be two args (or really the same as Args(Int,Int).) You may
937 find this useful for creating custom subtypes with complex matching rules that you
938 wish to reuse over many actions.
940 See L<Catalyst::RouteMatching> for more.
942 B<Note>: It is highly recommended to use L<Type::Tiny> for your type constraints over
943 other options. L<Type::Tiny> exposed a better meta data interface which allows us to
944 do more and better types of introspection driving tests and debugging.
946 =head2 Consumes('...')
948 Matches the current action against the content-type of the request. Typically
949 this is used when the request is a POST or PUT and you want to restrict the
950 submitted content type. For example, you might have an HTML for that either
951 returns classic url encoded form data, or JSON when Javascript is enabled. In
952 this case you may wish to match either incoming type to one of two different
953 actions, for properly processing.
957 sub is_json : Chained('start') Consumes('application/json') { ... }
958 sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
959 sub is_multipart : Chained('start') Consumes('multipart/form-data') { ... }
961 To reduce boilerplate, we include the following content type shortcuts:
965 sub is_json : Chained('start') Consume(JSON) { ... }
966 sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
967 sub is_multipart : Chained('start') Consumes(Multipart) { ... }
969 You may specify more than one match:
973 : Consumes('application/x-www-form-urlencoded')
974 : Consumes('multipart/form-data')
978 : Consumes(UrlEncoded)
979 : Consumes(Multipart)
981 Since it is a common case the shortcut C<HTMLForm> matches both
982 'application/x-www-form-urlencoded' and 'multipart/form-data'. Here's the full
983 list of available shortcuts:
985 JSON => 'application/json',
986 JS => 'application/javascript',
987 PERL => 'application/perl',
990 Plain => 'text/plain',
991 UrlEncoded => 'application/x-www-form-urlencoded',
992 Multipart => 'multipart/form-data',
993 HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
995 Please keep in mind that when dispatching, L<Catalyst> will match the first most
996 relevant case, so if you use the C<Consumes> attribute, you should place your
997 most accurate matches early in the Chain, and your 'catchall' actions last.
999 See L<Catalyst::ActionRole::ConsumesContent> for more.
1003 Allows you to specify a URI scheme for the action or action chain. For example
1004 you can required that a given path be C<https> or that it is a websocket endpoint
1005 C<ws> or C<wss>. For an action chain you may currently only have one defined
1008 package MyApp::Controller::Root;
1010 use base 'Catalyst::Controller';
1012 sub is_http :Path(scheme) Scheme(http) Args(0) {
1013 my ($self, $c) = @_;
1014 $c->response->body("is_http");
1017 sub is_https :Path(scheme) Scheme(https) Args(0) {
1018 my ($self, $c) = @_;
1019 $c->response->body("is_https");
1022 In the above example http://localhost/root/scheme would match the first
1023 action (is_http) but https://localhost/root/scheme would match the second.
1025 As an added benefit, if an action or action chain defines a Scheme, when using
1026 $c->uri_for the scheme of the generated URL will use what you define in the action
1027 or action chain (the current behavior is to set the scheme based on the current
1028 incoming request). This makes it easier to use uri_for on websites where some
1029 paths are secure and others are not. You may also use this to other schemes
1032 See L<Catalyst::ActionRole::Scheme> for more.
1034 =head1 OPTIONAL METHODS
1036 =head2 _parse_[$name]_attr
1038 Allows you to customize parsing of subroutine attributes.
1040 sub myaction1 :Path TwoArgs { ... }
1042 sub _parse_TwoArgs_attr {
1043 my ( $self, $c, $name, $value ) = @_;
1044 # $self -> controller instance
1049 Please note that this feature does not let you actually assign new functions
1050 to actions via subroutine attributes, but is really more for creating useful
1051 aliases to existing core and extended attributes, and transforms based on
1052 existing information (like from configuration). Code for actually doing
1053 something meaningful with the subroutine attributes will be located in the
1054 L<Catalyst::Action> classes (or your subclasses), L<Catalyst::Dispatcher> and
1055 in subclasses of L<Catalyst::DispatchType>. Remember these methods only get
1056 called basically once when the application is starting, not per request!
1060 Catalyst Contributors, see Catalyst.pm
1064 This library is free software. You can redistribute it and/or modify
1065 it under the same terms as Perl itself.