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 # This seems like total wack from 2009. Not sure
223 # why we'd take a ref on _application since we
224 # expect it to be a string... Seems like it was
225 # part of a whole bunch of changes related to the
226 # failed app/ctx stuff from years ago. However
227 # in cases where the controller gets called in
228 # application context, this now fails hard. I've
229 # added defensive 'if its a ref' code just to be
230 # safe but I don't think its really ever used
231 my $local_app = ref($self->_application) ?
232 ref($self->_application): $self->_application;
233 $case_s = $local_app->config->{case_sensitive};
235 confess("Can't figure out case_sensitive setting");
240 my $namespace = Catalyst::Utils::class2prefix($self->catalyst_component_name, $case_s) || '';
241 $self->$orig($namespace) if ref($self);
245 #Once again, this is probably better written as a builder method
246 around path_prefix => sub {
250 return $self->$orig if $self->has_path_prefix;
252 return $self->config->{path} if exists $self->config->{path};
254 my $namespace = $self->action_namespace(@_);
255 $self->$orig($namespace) if ref($self);
259 sub get_action_methods {
261 my $meta = find_meta($self) || confess("No metaclass setup for $self");
263 sprintf "Metaclass %s for %s cannot support register_actions.",
264 ref $meta, $meta->name,
265 ) unless $meta->can('get_nearest_methods_with_attributes');
266 my @methods = $meta->get_nearest_methods_with_attributes;
268 # actions specified via config are also action_methods
272 $meta->find_method_by_name($_)
273 || confess( sprintf 'Action "%s" is not available from controller %s',
275 } keys %{ $self->_controller_actions }
277 return uniq @methods;
281 sub register_actions {
282 my ( $self, $c ) = @_;
283 $self->register_action_methods( $c, $self->get_action_methods );
286 sub register_action_methods {
287 my ( $self, $c, @methods ) = @_;
288 my $class = $self->catalyst_component_name;
289 #this is still not correct for some reason.
290 my $namespace = $self->action_namespace($c);
293 if (!blessed($self) && $self eq $c && scalar(@methods)) {
294 my @really_bad_methods = grep { ! /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/ } map { $_->name } @methods;
295 if (scalar(@really_bad_methods)) {
296 $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.");
300 foreach my $method (@methods) {
301 my $name = $method->name;
302 # Horrible hack! All method metaclasses should have an attributes
303 # method, core Moose bug - see r13354.
304 my $attributes = $method->can('attributes') ? $method->attributes : [];
305 my $attrs = $self->_parse_attrs( $c, $name, @{ $attributes } );
306 if ( $attrs->{Private} && ( keys %$attrs > 1 ) ) {
307 $c->log->warn( 'Bad action definition "'
308 . join( ' ', @{ $attributes } )
309 . qq/" for "$class->$name"/ )
313 my $reverse = $namespace ? "${namespace}/${name}" : $name;
314 my $action = $self->create_action(
316 code => $method->body,
318 namespace => $namespace,
320 attributes => $attrs,
323 $c->dispatcher->register( $c, $action );
327 sub _apply_action_class_roles {
328 my ($self, $class, @roles) = @_;
330 load_class($_) for @roles;
331 my $meta = Moose::Meta::Class->initialize($class)->create_anon_class(
332 superclasses => [$class],
336 $meta->add_method(meta => sub { $meta });
345 my $class = (exists $args{attributes}{ActionClass}
346 ? $args{attributes}{ActionClass}[0]
347 : $self->_action_class);
357 my $class = $self->action_class(%args);
360 Moose->init_meta(for_class => $class)
361 unless Class::MOP::does_metaclass_exist($class);
363 unless ($args{name} =~ /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/) {
364 my @roles = $self->gather_action_roles(%args);
365 push @roles, $self->gather_default_action_roles(%args);
367 $class = $self->_apply_action_class_roles($class, @roles) if @roles;
373 : $self->config->{action_args}
377 %{ $action_args->{'*'} || {} },
378 %{ $action_args->{ $args{name} } || {} },
381 return $class->new({ %extra_args, %args });
384 sub gather_action_roles {
385 my ($self, %args) = @_;
387 (blessed $self ? $self->_action_roles : ()),
388 @{ $args{attributes}->{Does} || [] },
392 sub gather_default_action_roles {
393 my ($self, %args) = @_;
395 push @roles, 'Catalyst::ActionRole::HTTPMethods'
396 if $args{attributes}->{Method};
398 push @roles, 'Catalyst::ActionRole::ConsumesContent'
399 if $args{attributes}->{Consumes};
401 push @roles, 'Catalyst::ActionRole::Scheme'
402 if $args{attributes}->{Scheme};
404 push @roles, 'Catalyst::ActionRole::QueryMatching'
405 if $args{attributes}->{Query};
410 my ( $self, $c, $name, @attrs ) = @_;
414 foreach my $attr (@attrs) {
416 # Parse out :Foo(bar) into Foo => bar etc (and arrayify)
418 if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.+?)?\s*\))?$/ ) )
421 if ( defined $value ) {
422 ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
424 push( @{ $raw_attributes{$key} }, $value );
428 my ($actions_config, $all_actions_config);
430 $actions_config = $self->_controller_actions;
431 # No, you're not getting actions => { '*' => ... } with actions in MyApp.
432 $all_actions_config = $self->_all_actions_attributes;
434 my $cfg = $self->config;
435 $actions_config = $self->merge_config_hashes($cfg->{actions}, $cfg->{action});
436 $all_actions_config = {};
441 # Note we deep copy array refs here to stop crapping on config
442 # when attributes are parsed. RT#65463
443 exists $actions_config->{$name} ? map { ref($_) eq 'ARRAY' ? [ @$_ ] : $_ } %{ $actions_config->{$name } } : (),
446 # Private actions with additional attributes will raise a warning and then
447 # be ignored. Adding '*' arguments to the default _DISPATCH / etc. methods,
448 # which are Private, will prevent those from being registered. They should
449 # probably be turned into :Actions instead, or we might want to otherwise
450 # disambiguate between those built-in internal actions and user-level
452 %raw_attributes = (%{ $all_actions_config }, %raw_attributes)
453 unless $raw_attributes{Private};
455 my %final_attributes;
457 while (my ($key, $value) = each %raw_attributes){
458 my $new_attrs = $self->_parse_attr($c, $name, $key => $value );
459 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
462 return \%final_attributes;
466 my ($self, $c, $name, $key, $values) = @_;
468 my %final_attributes;
469 foreach my $value (ref($values) eq 'ARRAY' ? @$values : $values) {
470 my $meth = "_parse_${key}_attr";
471 if ( my $code = $self->can($meth) ) {
472 my %new_attrs = $self->$code( $c, $name, $value );
473 while (my ($new_key, $value) = each %new_attrs){
474 my $new_attrs = $key eq $new_key ?
475 { $new_key => [$value] } :
476 $self->_parse_attr($c, $name, $new_key => $value );
477 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
481 push( @{ $final_attributes{$key} }, $value );
485 return \%final_attributes;
488 sub _parse_Global_attr {
489 my ( $self, $c, $name, $value ) = @_;
490 # _parse_attr will call _parse_Path_attr for us
491 return Path => "/$name";
494 sub _parse_Absolute_attr { shift->_parse_Global_attr(@_); }
496 sub _parse_Local_attr {
497 my ( $self, $c, $name, $value ) = @_;
498 # _parse_attr will call _parse_Path_attr for us
499 return Path => $name;
502 sub _parse_Relative_attr { shift->_parse_Local_attr(@_); }
504 sub _parse_Path_attr {
505 my ( $self, $c, $name, $value ) = @_;
506 $value = '' if !defined $value;
507 if ( $value =~ m!^/! ) {
508 return ( 'Path', $value );
510 elsif ( length $value ) {
511 return ( 'Path', join( '/', $self->path_prefix($c), $value ) );
514 return ( 'Path', $self->path_prefix($c) );
518 sub _parse_Chained_attr {
519 my ($self, $c, $name, $value) = @_;
521 if (defined($value) && length($value)) {
523 $value = '/'.$self->action_namespace($c);
524 } elsif (my ($rel, $rest) = $value =~ /^((?:\.{2}\/)+)(.*)$/) {
525 my @parts = split '/', $self->action_namespace($c);
526 my @levels = split '/', $rel;
528 $value = '/'.join('/', @parts[0 .. $#parts - @levels], $rest);
529 } elsif ($value !~ m/^\//) {
530 my $action_ns = $self->action_namespace($c);
533 $value = '/'.join('/', $action_ns, $value);
535 $value = '/'.$value; # special case namespace '' (root)
542 return Chained => $value;
545 sub _parse_ChainedParent_attr {
546 my ($self, $c, $name, $value) = @_;
547 return $self->_parse_Chained_attr($c, $name, '../'.$name);
550 sub _parse_PathPrefix_attr {
551 my ( $self, $c ) = @_;
552 return PathPart => $self->path_prefix($c);
555 sub _parse_ActionClass_attr {
556 my ( $self, $c, $name, $value ) = @_;
557 my $appname = $self->_application;
558 $value = Catalyst::Utils::resolve_namespace($appname . '::Action', $self->_action_class, $value);
559 return ( 'ActionClass', $value );
562 sub _parse_MyAction_attr {
563 my ( $self, $c, $name, $value ) = @_;
565 my $appclass = Catalyst::Utils::class2appclass($self);
566 $value = "+${appclass}::Action::${value}";
568 return ( 'ActionClass', $value );
571 sub _parse_Does_attr {
572 my ($self, $app, $name, $value) = @_;
573 return Does => $self->_expand_role_shortname($value);
576 sub _parse_GET_attr { Method => 'GET' }
577 sub _parse_POST_attr { Method => 'POST' }
578 sub _parse_PUT_attr { Method => 'PUT' }
579 sub _parse_DELETE_attr { Method => 'DELETE' }
580 sub _parse_OPTIONS_attr { Method => 'OPTIONS' }
581 sub _parse_HEAD_attr { Method => 'HEAD' }
582 sub _parse_PATCH_attr { Method => 'PATCH' }
584 sub _expand_role_shortname {
585 my ($self, @shortnames) = @_;
586 my $app = $self->_application;
588 my $prefix = $self->can('_action_role_prefix') ? $self->_action_role_prefix : ['Catalyst::ActionRole::'];
589 my @prefixes = (qq{${app}::ActionRole::}, @$prefix);
591 return String::RewritePrefix->rewrite(
593 my $loaded = load_first_existing_class(
594 map { "$_$_[0]" } @prefixes
596 return first { $loaded =~ /^$_/ }
597 sort { length $b <=> length $a } @prefixes;
605 __PACKAGE__->meta->make_immutable;
613 Like any other L<Catalyst::Component>, controllers have a config hash,
614 accessible through $self->config from the controller actions. Some
615 settings are in use by the Catalyst framework:
619 This specifies the internal namespace the controller should be bound
620 to. By default the controller is bound to the URI version of the
621 controller name. For instance controller 'MyApp::Controller::Foo::Bar'
622 will be bound to 'foo/bar'. The default Root controller is an example
623 of setting namespace to '' (the null string).
627 Sets 'path_prefix', as described below.
631 Allows you to set the attributes that the dispatcher creates actions out of.
632 This allows you to do 'rails style routes', or override some of the
633 attribute definitions of actions composed from Roles.
634 You can set arguments globally (for all actions of the controller) and
635 specifically (for a single action).
639 '*' => { Chained => 'base', Args => 0 },
640 base => { Chained => '/', PathPart => '', CaptureArgs => 0 },
644 In the case above every sub in the package would be made into a Chain
645 endpoint with a URI the same as the sub name for each sub, chained
646 to the sub named C<base>. Ergo dispatch to C</example> would call the
647 C<base> method, then the C<example> method.
651 Allows you to set constructor arguments on your actions. You can set arguments
652 globally and specifically (as above).
653 This is particularly useful when using C<ActionRole>s
654 (L<Catalyst::Controller::ActionRole>) and custom C<ActionClass>es.
658 '*' => { globalarg1 => 'hello', globalarg2 => 'goodbye' },
659 'specific_action' => { customarg => 'arg1' },
663 In the case above the action class associated with C<specific_action> would get
664 passed the following arguments, in addition to the normal action constructor
665 arguments, when it is instantiated:
667 (globalarg1 => 'hello', globalarg2 => 'goodbye', customarg => 'arg1')
671 =head2 BUILDARGS ($app, @args)
673 From L<Catalyst::Component::ApplicationAttribute>, stashes the application
674 instance as $self->_application.
676 =head2 $self->action_for('name')
678 Returns the Catalyst::Action object (if any) for a given method name
681 =head2 $self->action_namespace($c)
683 Returns the private namespace for actions in this component. Defaults
684 to a value from the controller name (for
685 e.g. MyApp::Controller::Foo::Bar becomes "foo/bar") or can be
686 overridden from the "namespace" config key.
689 =head2 $self->path_prefix($c)
691 Returns the default path prefix for :PathPrefix, :Local and
692 relative :Path actions in this component. Defaults to the action_namespace or
693 can be overridden from the "path" config key.
695 =head2 $self->register_actions($c)
697 Finds all applicable actions for this component, creates
698 Catalyst::Action objects (using $self->create_action) for them and
699 registers them with $c->dispatcher.
701 =head2 $self->get_action_methods()
703 Returns a list of L<Moose::Meta::Method> objects, doing the
704 L<MooseX::MethodAttributes::Role::Meta::Method> role, which are the set of
705 action methods for this package.
707 =head2 $self->register_action_methods($c, @methods)
709 Creates action objects for a set of action methods using C< create_action >,
710 and registers them with the dispatcher.
712 =head2 $self->action_class(%args)
714 Used when a controller is creating an action to determine the correct base
717 =head2 $self->create_action(%args)
719 Called with a hash of data to be use for construction of a new
720 Catalyst::Action (or appropriate sub/alternative class) object.
722 =head2 $self->gather_action_roles(\%action_args)
724 Gathers the list of roles to apply to an action with the given %action_args.
726 =head2 $self->gather_default_action_roles(\%action_args)
728 returns a list of action roles to be applied based on core, builtin rules.
729 Currently only the L<Catalyst::ActionRole::HTTPMethods> role is applied
732 =head2 $self->_application
736 Returns the application instance stored by C<new()>
738 =head1 ACTION SUBROUTINE ATTRIBUTES
740 Please see L<Catalyst::Manual::Intro> for more details
742 Think of action attributes as a sort of way to record metadata about an action,
743 similar to how annotations work in other languages you might have heard of.
744 Generally L<Catalyst> uses these to influence how the dispatcher sees your
745 action and when it will run it in response to an incoming request. They can
746 also be used for other things. Here's a summary, but you should refer to the
747 linked manual page for additional help.
751 sub homepage :Global { ... }
753 A global action defined in any controller always runs relative to your root.
754 So the above is the same as:
756 sub myaction :Path("/homepage") { ... }
760 Status: Deprecated alias to L</Global>.
764 Alias to "Path("$action_name"). The following two actions are the same:
766 sub myaction :Local { ... }
767 sub myaction :Path('myaction') { ... }
771 Status: Deprecated alias to L</Local>
775 Handle various types of paths:
777 package MyApp::Controller::Baz {
781 sub myaction1 :Path { ... } # -> /baz
782 sub myaction2 :Path('foo') { ... } # -> /baz/foo
783 sub myaction2 :Path('/bar') { ... } # -> /bar
786 This is a general toolbox for attaching your action to a given path.
793 B<Status: Deprecated.> Use Chained methods or other techniques.
794 If you really depend on this, install the standalone
795 L<Catalyst::DispatchType::Regex> distribution.
797 A global way to match a give regular expression in the incoming request path.
803 B<Status: Deprecated.> Use Chained methods or other techniques.
804 If you really depend on this, install the standalone
805 L<Catalyst::DispatchType::Regex> distribution.
807 Like L</Regex> but scoped under the namespace of the containing controller
819 Allowed values for CaptureArgs is a single integer (CaptureArgs(2), meaning two
820 allowed) or you can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny>
821 named constraint such as CaptureArgs(Int,Str) would require two args with
822 the first being a Integer and the second a string. You may declare your own
823 custom type constraints and import them into the controller namespace:
825 package MyApp::Controller::Root;
828 use MooseX::MethodAttributes;
829 use MyApp::Types qw/Int/;
831 extends 'Catalyst::Controller';
833 sub chain_base :Chained(/) CaptureArgs(1) { }
835 sub any_priority_chain :Chained(chain_base) PathPart('') Args(1) { }
837 sub int_priority_chain :Chained(chain_base) PathPart('') Args(Int) { }
839 See L<Catalyst::RouteMatching> for more.
841 Please see L<Catalyst::DispatchType::Chained> for more.
845 Set the base class for the action, defaults to L</Catalyst::Action>. It is now
846 preferred to use L</Does>.
850 Set the ActionClass using a custom Action in your project namespace.
852 The following is exactly the same:
854 sub foo_action1 : Local ActionClass('+MyApp::Action::Bar') { ... }
855 sub foo_action2 : Local MyAction('Bar') { ... }
859 package MyApp::Controller::Zoo;
861 sub foo : Local Does('Moo') { ... } # Catalyst::ActionRole::
862 sub bar : Local Does('~Moo') { ... } # MyApp::ActionRole::Moo
863 sub baz : Local Does('+MyApp::ActionRole::Moo') { ... }
881 Sets the give action path to match the specified HTTP method, or via one of the
882 broadly accepted methods of overriding the 'true' method (see
883 L<Catalyst::ActionRole::HTTPMethods>).
887 When used with L</Path> indicates the number of arguments expected in
888 the path. However if no Args value is set, assumed to 'slurp' all
889 remaining path pars under this namespace.
891 Allowed values for Args is a single integer (Args(2), meaning two allowed) or you
892 can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny> named constraint such
893 as Args(Int,Str) would require two args with the first being a Integer and the
894 second a string. You may declare your own custom type constraints and import
895 them into the controller namespace:
897 package MyApp::Controller::Root;
900 use MooseX::MethodAttributes;
901 use MyApp::Types qw/Tuple Int Str StrMatch UserId/;
903 extends 'Catalyst::Controller';
905 sub user :Local Args(UserId) {
906 my ($self, $c, $int) = @_;
909 sub an_int :Local Args(Int) {
910 my ($self, $c, $int) = @_;
913 sub many_ints :Local Args(ArrayRef[Int]) {
914 my ($self, $c, @ints) = @_;
917 sub match :Local Args(StrMatch[qr{\d\d-\d\d-\d\d}]) {
918 my ($self, $c, $int) = @_;
921 If you choose not to use imported type constraints (like L<Type::Tiny>, or <MooseX::Types>
922 you may use L<Moose> 'stringy' types however just like when you use these types in your
923 declared attributes you must quote them:
925 sub my_moose_type :Local Args('Int') { ... }
927 If you use 'reference' type constraints (such as ArrayRef[Int]) that have an unknown
928 number of allowed matches, we set this the same way "Args" is. Please keep in mind
929 that actions with an undetermined number of args match at lower precedence than those
930 with a fixed number. You may use reference types such as Tuple from L<Types::Standard>
931 that allows you to fix the number of allowed args. For example Args(Tuple[Int,Int])
932 would be determined to be two args (or really the same as Args(Int,Int).) You may
933 find this useful for creating custom subtypes with complex matching rules that you
934 wish to reuse over many actions.
936 See L<Catalyst::RouteMatching> for more.
938 =head2 Consumes('...')
940 Matches the current action against the content-type of the request. Typically
941 this is used when the request is a POST or PUT and you want to restrict the
942 submitted content type. For example, you might have an HTML for that either
943 returns classic url encoded form data, or JSON when Javascript is enabled. In
944 this case you may wish to match either incoming type to one of two different
945 actions, for properly processing.
949 sub is_json : Chained('start') Consumes('application/json') { ... }
950 sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
951 sub is_multipart : Chained('start') Consumes('multipart/form-data') { ... }
953 To reduce boilerplate, we include the following content type shortcuts:
957 sub is_json : Chained('start') Consume(JSON) { ... }
958 sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
959 sub is_multipart : Chained('start') Consumes(Multipart) { ... }
961 You may specify more than one match:
965 : Consumes('application/x-www-form-urlencoded')
966 : Consumes('multipart/form-data')
970 : Consumes(UrlEncoded)
971 : Consumes(Multipart)
973 Since it is a common case the shortcut C<HTMLForm> matches both
974 'application/x-www-form-urlencoded' and 'multipart/form-data'. Here's the full
975 list of available shortcuts:
977 JSON => 'application/json',
978 JS => 'application/javascript',
979 PERL => 'application/perl',
982 Plain => 'text/plain',
983 UrlEncoded => 'application/x-www-form-urlencoded',
984 Multipart => 'multipart/form-data',
985 HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
987 Please keep in mind that when dispatching, L<Catalyst> will match the first most
988 relevant case, so if you use the C<Consumes> attribute, you should place your
989 most accurate matches early in the Chain, and your 'catchall' actions last.
991 See L<Catalyst::ActionRole::ConsumesContent> for more.
995 Allows you to specify a URI scheme for the action or action chain. For example
996 you can required that a given path be C<https> or that it is a websocket endpoint
997 C<ws> or C<wss>. For an action chain you may currently only have one defined
1000 package MyApp::Controller::Root;
1002 use base 'Catalyst::Controller';
1004 sub is_http :Path(scheme) Scheme(http) Args(0) {
1005 my ($self, $c) = @_;
1006 $c->response->body("is_http");
1009 sub is_https :Path(scheme) Scheme(https) Args(0) {
1010 my ($self, $c) = @_;
1011 $c->response->body("is_https");
1014 In the above example http://localhost/root/scheme would match the first
1015 action (is_http) but https://localhost/root/scheme would match the second.
1017 As an added benefit, if an action or action chain defines a Scheme, when using
1018 $c->uri_for the scheme of the generated URL will use what you define in the action
1019 or action chain (the current behavior is to set the scheme based on the current
1020 incoming request). This makes it easier to use uri_for on websites where some
1021 paths are secure and others are not. You may also use this to other schemes
1024 See L<Catalyst::ActionRole::Scheme> for more.
1026 =head1 OPTIONAL METHODS
1028 =head2 _parse_[$name]_attr
1030 Allows you to customize parsing of subroutine attributes.
1032 sub myaction1 :Path TwoArgs { ... }
1034 sub _parse_TwoArgs_attr {
1035 my ( $self, $c, $name, $value ) = @_;
1036 # $self -> controller instance
1041 Please note that this feature does not let you actually assign new functions
1042 to actions via subroutine attributes, but is really more for creating useful
1043 aliases to existing core and extended attributes, and transforms based on
1044 existing information (like from configuration). Code for actually doing
1045 something meaningful with the subroutine attributes will be located in the
1046 L<Catalyst::Action> classes (or your subclasses), L<Catalyst::Dispatcher> and
1047 in subclasses of L<Catalyst::DispatchType>. Remember these methods only get
1048 called basically once when the application is starting, not per request!
1052 Catalyst Contributors, see Catalyst.pm
1056 This library is free software. You can redistribute it and/or modify
1057 it under the same terms as Perl itself.