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 $auto->dispatch( $c );
159 return 0 unless $c->state;
161 return $c->state || 1;
164 sub _ACTION : Private {
165 my ( $self, $c ) = @_;
167 && $c->action->can('execute')
168 && defined $c->req->action )
170 $c->action->dispatch( $c );
172 #If there is an error, all bets off
173 if( @{ $c->error }) {
174 return !@{ $c->error };
176 return $c->state || 1;
181 my ( $self, $c ) = @_;
182 my $end = ( $c->get_actions( 'end', $c->namespace ) )[-1];
183 return 1 unless $end;
184 $end->dispatch( $c );
185 return !@{ $c->error };
189 my ( $self, $name ) = @_;
190 my $app = ($self->isa('Catalyst') ? $self : $self->_application);
191 return $app->dispatcher->get_action($name, $self->action_namespace);
194 #my opinion is that this whole sub really should be a builder method, not
195 #something that happens on every call. Anyone else disagree?? -- groditi
196 ## -- apparently this is all just waiting for app/ctx split
197 around action_namespace => sub {
199 my ( $self, $c ) = @_;
201 my $class = ref($self) || $self;
202 my $appclass = ref($c) || $c;
204 return $self->$orig if $self->has_action_namespace;
206 return $class->config->{namespace} if exists $class->config->{namespace};
211 $case_s = $appclass->config->{case_sensitive};
213 if ($self->isa('Catalyst')) {
214 $case_s = $class->config->{case_sensitive};
217 $case_s = ref($self->_application)->config->{case_sensitive};
219 confess("Can't figure out case_sensitive setting");
224 my $namespace = Catalyst::Utils::class2prefix($self->catalyst_component_name, $case_s) || '';
225 $self->$orig($namespace) if ref($self);
229 #Once again, this is probably better written as a builder method
230 around path_prefix => sub {
234 return $self->$orig if $self->has_path_prefix;
236 return $self->config->{path} if exists $self->config->{path};
238 my $namespace = $self->action_namespace(@_);
239 $self->$orig($namespace) if ref($self);
243 sub get_action_methods {
245 my $meta = find_meta($self) || confess("No metaclass setup for $self");
247 sprintf "Metaclass %s for %s cannot support register_actions.",
248 ref $meta, $meta->name,
249 ) unless $meta->can('get_nearest_methods_with_attributes');
250 my @methods = $meta->get_nearest_methods_with_attributes;
252 # actions specified via config are also action_methods
256 $meta->find_method_by_name($_)
257 || confess( sprintf 'Action "%s" is not available from controller %s',
259 } keys %{ $self->_controller_actions }
261 return uniq @methods;
265 sub register_actions {
266 my ( $self, $c ) = @_;
267 $self->register_action_methods( $c, $self->get_action_methods );
270 sub register_action_methods {
271 my ( $self, $c, @methods ) = @_;
272 my $class = $self->catalyst_component_name;
273 #this is still not correct for some reason.
274 my $namespace = $self->action_namespace($c);
277 if (!blessed($self) && $self eq $c && scalar(@methods)) {
278 my @really_bad_methods = grep { ! /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/ } map { $_->name } @methods;
279 if (scalar(@really_bad_methods)) {
280 $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.");
284 foreach my $method (@methods) {
285 my $name = $method->name;
286 # Horrible hack! All method metaclasses should have an attributes
287 # method, core Moose bug - see r13354.
288 my $attributes = $method->can('attributes') ? $method->attributes : [];
289 my $attrs = $self->_parse_attrs( $c, $name, @{ $attributes } );
290 if ( $attrs->{Private} && ( keys %$attrs > 1 ) ) {
291 $c->log->warn( 'Bad action definition "'
292 . join( ' ', @{ $attributes } )
293 . qq/" for "$class->$name"/ )
297 my $reverse = $namespace ? "${namespace}/${name}" : $name;
298 my $action = $self->create_action(
300 code => $method->body,
302 namespace => $namespace,
304 attributes => $attrs,
307 $c->dispatcher->register( $c, $action );
311 sub _apply_action_class_roles {
312 my ($self, $class, @roles) = @_;
314 load_class($_) for @roles;
315 my $meta = Moose::Meta::Class->initialize($class)->create_anon_class(
316 superclasses => [$class],
320 $meta->add_method(meta => sub { $meta });
329 my $class = (exists $args{attributes}{ActionClass}
330 ? $args{attributes}{ActionClass}[0]
331 : $self->_action_class);
341 my $class = $self->action_class(%args);
344 Moose->init_meta(for_class => $class)
345 unless Class::MOP::does_metaclass_exist($class);
347 unless ($args{name} =~ /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/) {
348 my @roles = $self->gather_action_roles(%args);
349 push @roles, $self->gather_default_action_roles(%args);
351 $class = $self->_apply_action_class_roles($class, @roles) if @roles;
357 : $self->config->{action_args}
361 %{ $action_args->{'*'} || {} },
362 %{ $action_args->{ $args{name} } || {} },
365 return $class->new({ %extra_args, %args });
368 sub gather_action_roles {
369 my ($self, %args) = @_;
371 (blessed $self ? $self->_action_roles : ()),
372 @{ $args{attributes}->{Does} || [] },
376 sub gather_default_action_roles {
377 my ($self, %args) = @_;
379 push @roles, 'Catalyst::ActionRole::HTTPMethods'
380 if $args{attributes}->{Method};
382 push @roles, 'Catalyst::ActionRole::ConsumesContent'
383 if $args{attributes}->{Consumes};
385 push @roles, 'Catalyst::ActionRole::Scheme'
386 if $args{attributes}->{Scheme};
388 push @roles, 'Catalyst::ActionRole::QueryMatching'
389 if $args{attributes}->{Query};
394 my ( $self, $c, $name, @attrs ) = @_;
398 foreach my $attr (@attrs) {
400 # Parse out :Foo(bar) into Foo => bar etc (and arrayify)
402 if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.*?)\s*\))?$/ ) )
405 if ( defined $value ) {
406 ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
408 push( @{ $raw_attributes{$key} }, $value );
412 my ($actions_config, $all_actions_config);
414 $actions_config = $self->_controller_actions;
415 # No, you're not getting actions => { '*' => ... } with actions in MyApp.
416 $all_actions_config = $self->_all_actions_attributes;
418 my $cfg = $self->config;
419 $actions_config = $self->merge_config_hashes($cfg->{actions}, $cfg->{action});
420 $all_actions_config = {};
425 # Note we deep copy array refs here to stop crapping on config
426 # when attributes are parsed. RT#65463
427 exists $actions_config->{$name} ? map { ref($_) eq 'ARRAY' ? [ @$_ ] : $_ } %{ $actions_config->{$name } } : (),
430 # Private actions with additional attributes will raise a warning and then
431 # be ignored. Adding '*' arguments to the default _DISPATCH / etc. methods,
432 # which are Private, will prevent those from being registered. They should
433 # probably be turned into :Actions instead, or we might want to otherwise
434 # disambiguate between those built-in internal actions and user-level
436 %raw_attributes = (%{ $all_actions_config }, %raw_attributes)
437 unless $raw_attributes{Private};
439 my %final_attributes;
441 while (my ($key, $value) = each %raw_attributes){
442 my $new_attrs = $self->_parse_attr($c, $name, $key => $value );
443 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
446 return \%final_attributes;
450 my ($self, $c, $name, $key, $values) = @_;
452 my %final_attributes;
453 foreach my $value (ref($values) eq 'ARRAY' ? @$values : $values) {
454 my $meth = "_parse_${key}_attr";
455 if ( my $code = $self->can($meth) ) {
456 my %new_attrs = $self->$code( $c, $name, $value );
457 while (my ($new_key, $value) = each %new_attrs){
458 my $new_attrs = $key eq $new_key ?
459 { $new_key => [$value] } :
460 $self->_parse_attr($c, $name, $new_key => $value );
461 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
465 push( @{ $final_attributes{$key} }, $value );
469 return \%final_attributes;
472 sub _parse_Global_attr {
473 my ( $self, $c, $name, $value ) = @_;
474 # _parse_attr will call _parse_Path_attr for us
475 return Path => "/$name";
478 sub _parse_Absolute_attr { shift->_parse_Global_attr(@_); }
480 sub _parse_Local_attr {
481 my ( $self, $c, $name, $value ) = @_;
482 # _parse_attr will call _parse_Path_attr for us
483 return Path => $name;
486 sub _parse_Relative_attr { shift->_parse_Local_attr(@_); }
488 sub _parse_Path_attr {
489 my ( $self, $c, $name, $value ) = @_;
490 $value = '' if !defined $value;
491 if ( $value =~ m!^/! ) {
492 return ( 'Path', $value );
494 elsif ( length $value ) {
495 return ( 'Path', join( '/', $self->path_prefix($c), $value ) );
498 return ( 'Path', $self->path_prefix($c) );
502 sub _parse_Chained_attr {
503 my ($self, $c, $name, $value) = @_;
505 if (defined($value) && length($value)) {
507 $value = '/'.$self->action_namespace($c);
508 } elsif (my ($rel, $rest) = $value =~ /^((?:\.{2}\/)+)(.*)$/) {
509 my @parts = split '/', $self->action_namespace($c);
510 my @levels = split '/', $rel;
512 $value = '/'.join('/', @parts[0 .. $#parts - @levels], $rest);
513 } elsif ($value !~ m/^\//) {
514 my $action_ns = $self->action_namespace($c);
517 $value = '/'.join('/', $action_ns, $value);
519 $value = '/'.$value; # special case namespace '' (root)
526 return Chained => $value;
529 sub _parse_ChainedParent_attr {
530 my ($self, $c, $name, $value) = @_;
531 return $self->_parse_Chained_attr($c, $name, '../'.$name);
534 sub _parse_PathPrefix_attr {
535 my ( $self, $c ) = @_;
536 return PathPart => $self->path_prefix($c);
539 sub _parse_ActionClass_attr {
540 my ( $self, $c, $name, $value ) = @_;
541 my $appname = $self->_application;
542 $value = Catalyst::Utils::resolve_namespace($appname . '::Action', $self->_action_class, $value);
543 return ( 'ActionClass', $value );
546 sub _parse_MyAction_attr {
547 my ( $self, $c, $name, $value ) = @_;
549 my $appclass = Catalyst::Utils::class2appclass($self);
550 $value = "+${appclass}::Action::${value}";
552 return ( 'ActionClass', $value );
555 sub _parse_Does_attr {
556 my ($self, $app, $name, $value) = @_;
557 return Does => $self->_expand_role_shortname($value);
560 sub _parse_GET_attr { Method => 'GET' }
561 sub _parse_POST_attr { Method => 'POST' }
562 sub _parse_PUT_attr { Method => 'PUT' }
563 sub _parse_DELETE_attr { Method => 'DELETE' }
564 sub _parse_OPTIONS_attr { Method => 'OPTIONS' }
565 sub _parse_HEAD_attr { Method => 'HEAD' }
566 sub _parse_PATCH_attr { Method => 'PATCH' }
568 sub _expand_role_shortname {
569 my ($self, @shortnames) = @_;
570 my $app = $self->_application;
572 my $prefix = $self->can('_action_role_prefix') ? $self->_action_role_prefix : ['Catalyst::ActionRole::'];
573 my @prefixes = (qq{${app}::ActionRole::}, @$prefix);
575 return String::RewritePrefix->rewrite(
577 my $loaded = load_first_existing_class(
578 map { "$_$_[0]" } @prefixes
580 return first { $loaded =~ /^$_/ }
581 sort { length $b <=> length $a } @prefixes;
589 __PACKAGE__->meta->make_immutable;
597 Like any other L<Catalyst::Component>, controllers have a config hash,
598 accessible through $self->config from the controller actions. Some
599 settings are in use by the Catalyst framework:
603 This specifies the internal namespace the controller should be bound
604 to. By default the controller is bound to the URI version of the
605 controller name. For instance controller 'MyApp::Controller::Foo::Bar'
606 will be bound to 'foo/bar'. The default Root controller is an example
607 of setting namespace to '' (the null string).
611 Sets 'path_prefix', as described below.
615 Allows you to set the attributes that the dispatcher creates actions out of.
616 This allows you to do 'rails style routes', or override some of the
617 attribute definitions of actions composed from Roles.
618 You can set arguments globally (for all actions of the controller) and
619 specifically (for a single action).
623 '*' => { Chained => 'base', Args => 0 },
624 base => { Chained => '/', PathPart => '', CaptureArgs => 0 },
628 In the case above every sub in the package would be made into a Chain
629 endpoint with a URI the same as the sub name for each sub, chained
630 to the sub named C<base>. Ergo dispatch to C</example> would call the
631 C<base> method, then the C<example> method.
635 Allows you to set constructor arguments on your actions. You can set arguments
636 globally and specifically (as above).
637 This is particularly useful when using C<ActionRole>s
638 (L<Catalyst::Controller::ActionRole>) and custom C<ActionClass>es.
642 '*' => { globalarg1 => 'hello', globalarg2 => 'goodbye' },
643 'specific_action' => { customarg => 'arg1' },
647 In the case above the action class associated with C<specific_action> would get
648 passed the following arguments, in addition to the normal action constructor
649 arguments, when it is instantiated:
651 (globalarg1 => 'hello', globalarg2 => 'goodbye', customarg => 'arg1')
655 =head2 BUILDARGS ($app, @args)
657 From L<Catalyst::Component::ApplicationAttribute>, stashes the application
658 instance as $self->_application.
660 =head2 $self->action_for('name')
662 Returns the Catalyst::Action object (if any) for a given method name
665 =head2 $self->action_namespace($c)
667 Returns the private namespace for actions in this component. Defaults
668 to a value from the controller name (for
669 e.g. MyApp::Controller::Foo::Bar becomes "foo/bar") or can be
670 overridden from the "namespace" config key.
673 =head2 $self->path_prefix($c)
675 Returns the default path prefix for :PathPrefix, :Local and
676 relative :Path actions in this component. Defaults to the action_namespace or
677 can be overridden from the "path" config key.
679 =head2 $self->register_actions($c)
681 Finds all applicable actions for this component, creates
682 Catalyst::Action objects (using $self->create_action) for them and
683 registers them with $c->dispatcher.
685 =head2 $self->get_action_methods()
687 Returns a list of L<Moose::Meta::Method> objects, doing the
688 L<MooseX::MethodAttributes::Role::Meta::Method> role, which are the set of
689 action methods for this package.
691 =head2 $self->register_action_methods($c, @methods)
693 Creates action objects for a set of action methods using C< create_action >,
694 and registers them with the dispatcher.
696 =head2 $self->action_class(%args)
698 Used when a controller is creating an action to determine the correct base
701 =head2 $self->create_action(%args)
703 Called with a hash of data to be use for construction of a new
704 Catalyst::Action (or appropriate sub/alternative class) object.
706 =head2 $self->gather_action_roles(\%action_args)
708 Gathers the list of roles to apply to an action with the given %action_args.
710 =head2 $self->gather_default_action_roles(\%action_args)
712 returns a list of action roles to be applied based on core, builtin rules.
713 Currently only the L<Catalyst::ActionRole::HTTPMethods> role is applied
716 =head2 $self->_application
720 Returns the application instance stored by C<new()>
722 =head1 ACTION SUBROUTINE ATTRIBUTES
724 Please see L<Catalyst::Manual::Intro> for more details
726 Think of action attributes as a sort of way to record metadata about an action,
727 similar to how annotations work in other languages you might have heard of.
728 Generally L<Catalyst> uses these to influence how the dispatcher sees your
729 action and when it will run it in response to an incoming request. They can
730 also be used for other things. Here's a summary, but you should refer to the
731 linked manual page for additional help.
735 sub homepage :Global { ... }
737 A global action defined in any controller always runs relative to your root.
738 So the above is the same as:
740 sub myaction :Path("/homepage") { ... }
744 Status: Deprecated alias to L</Global>.
748 Alias to "Path("$action_name"). The following two actions are the same:
750 sub myaction :Local { ... }
751 sub myaction :Path('myaction') { ... }
755 Status: Deprecated alias to L</Local>
759 Handle various types of paths:
761 package MyApp::Controller::Baz {
765 sub myaction1 :Path { ... } # -> /baz
766 sub myaction2 :Path('foo') { ... } # -> /baz/foo
767 sub myaction2 :Path('/bar') { ... } # -> /bar
770 This is a general toolbox for attaching your action to a given path.
777 B<Status: Deprecated.> Use Chained methods or other techniques.
778 If you really depend on this, install the standalone
779 L<Catalyst::DispatchType::Regex> distribution.
781 A global way to match a give regular expression in the incoming request path.
787 B<Status: Deprecated.> Use Chained methods or other techniques.
788 If you really depend on this, install the standalone
789 L<Catalyst::DispatchType::Regex> distribution.
791 Like L</Regex> but scoped under the namespace of the containing controller
803 Allowed values for CaptureArgs is a single integer (CaptureArgs(2), meaning two
804 allowed) or you can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny>
805 named constraint such as CaptureArgs(Int,Str) would require two args with
806 the first being a Integer and the second a string. You may declare your own
807 custom type constraints and import them into the controller namespace:
809 package MyApp::Controller::Root;
812 use MooseX::MethodAttributes;
813 use MyApp::Types qw/Int/;
815 extends 'Catalyst::Controller';
817 sub chain_base :Chained(/) CaptureArgs(1) { }
819 sub any_priority_chain :Chained(chain_base) PathPart('') Args(1) { }
821 sub int_priority_chain :Chained(chain_base) PathPart('') Args(Int) { }
823 See L<Catalyst::RouteMatching> for more.
825 Please see L<Catalyst::DispatchType::Chained> for more.
829 Set the base class for the action, defaults to L</Catalyst::Action>. It is now
830 preferred to use L</Does>.
834 Set the ActionClass using a custom Action in your project namespace.
836 The following is exactly the same:
838 sub foo_action1 : Local ActionClass('+MyApp::Action::Bar') { ... }
839 sub foo_action2 : Local MyAction('Bar') { ... }
843 package MyApp::Controller::Zoo;
845 sub foo : Local Does('Moo') { ... } # Catalyst::ActionRole::
846 sub bar : Local Does('~Moo') { ... } # MyApp::ActionRole::Moo
847 sub baz : Local Does('+MyApp::ActionRole::Moo') { ... }
865 Sets the give action path to match the specified HTTP method, or via one of the
866 broadly accepted methods of overriding the 'true' method (see
867 L<Catalyst::ActionRole::HTTPMethods>).
871 When used with L</Path> indicates the number of arguments expected in
872 the path. However if no Args value is set, assumed to 'slurp' all
873 remaining path pars under this namespace.
875 Allowed values for Args is a single integer (Args(2), meaning two allowed) or you
876 can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny> named constraint such
877 as Args(Int,Str) would require two args with the first being a Integer and the
878 second a string. You may declare your own custom type constraints and import
879 them into the controller namespace:
881 package MyApp::Controller::Root;
884 use MooseX::MethodAttributes;
885 use MyApp::Types qw/Tuple Int Str StrMatch UserId/;
887 extends 'Catalyst::Controller';
889 sub user :Local Args(UserId) {
890 my ($self, $c, $int) = @_;
893 sub an_int :Local Args(Int) {
894 my ($self, $c, $int) = @_;
897 sub many_ints :Local Args(ArrayRef[Int]) {
898 my ($self, $c, @ints) = @_;
901 sub match :Local Args(StrMatch[qr{\d\d-\d\d-\d\d}]) {
902 my ($self, $c, $int) = @_;
905 If you choose not to use imported type constraints (like L<Type::Tiny>, or <MooseX::Types>
906 you may use L<Moose> 'stringy' types however just like when you use these types in your
907 declared attributes you must quote them:
909 sub my_moose_type :Local Args('Int') { ... }
911 If you use 'reference' type constraints (such as ArrayRef[Int]) that have an unknown
912 number of allowed matches, we set this the same way "Args" is. Please keep in mind
913 that actions with an undetermined number of args match at lower precedence than those
914 with a fixed number. You may use reference types such as Tuple from L<Types::Standard>
915 that allows you to fix the number of allowed args. For example Args(Tuple[Int,Int])
916 would be determined to be two args (or really the same as Args(Int,Int).) You may
917 find this useful for creating custom subtypes with complex matching rules that you
918 wish to reuse over many actions.
920 See L<Catalyst::RouteMatching> for more.
922 =head2 Consumes('...')
924 Matches the current action against the content-type of the request. Typically
925 this is used when the request is a POST or PUT and you want to restrict the
926 submitted content type. For example, you might have an HTML for that either
927 returns classic url encoded form data, or JSON when Javascript is enabled. In
928 this case you may wish to match either incoming type to one of two different
929 actions, for properly processing.
933 sub is_json : Chained('start') Consumes('application/json') { ... }
934 sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
935 sub is_multipart : Chained('start') Consumes('multipart/form-data') { ... }
937 To reduce boilerplate, we include the following content type shortcuts:
941 sub is_json : Chained('start') Consume(JSON) { ... }
942 sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
943 sub is_multipart : Chained('start') Consumes(Multipart) { ... }
945 You may specify more than one match:
949 : Consumes('application/x-www-form-urlencoded')
950 : Consumes('multipart/form-data')
954 : Consumes(UrlEncoded)
955 : Consumes(Multipart)
957 Since it is a common case the shortcut C<HTMLForm> matches both
958 'application/x-www-form-urlencoded' and 'multipart/form-data'. Here's the full
959 list of available shortcuts:
961 JSON => 'application/json',
962 JS => 'application/javascript',
963 PERL => 'application/perl',
966 Plain => 'text/plain',
967 UrlEncoded => 'application/x-www-form-urlencoded',
968 Multipart => 'multipart/form-data',
969 HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
971 Please keep in mind that when dispatching, L<Catalyst> will match the first most
972 relevant case, so if you use the C<Consumes> attribute, you should place your
973 most accurate matches early in the Chain, and your 'catchall' actions last.
975 See L<Catalyst::ActionRole::ConsumesContent> for more.
979 Allows you to specify a URI scheme for the action or action chain. For example
980 you can required that a given path be C<https> or that it is a websocket endpoint
981 C<ws> or C<wss>. For an action chain you may currently only have one defined
984 package MyApp::Controller::Root;
986 use base 'Catalyst::Controller';
988 sub is_http :Path(scheme) Scheme(http) Args(0) {
990 $c->response->body("is_http");
993 sub is_https :Path(scheme) Scheme(https) Args(0) {
995 $c->response->body("is_https");
998 In the above example http://localhost/root/scheme would match the first
999 action (is_http) but https://localhost/root/scheme would match the second.
1001 As an added benefit, if an action or action chain defines a Scheme, when using
1002 $c->uri_for the scheme of the generated URL will use what you define in the action
1003 or action chain (the current behavior is to set the scheme based on the current
1004 incoming request). This makes it easier to use uri_for on websites where some
1005 paths are secure and others are not. You may also use this to other schemes
1008 See L<Catalyst::ActionRole::Scheme> for more.
1010 =head1 OPTIONAL METHODS
1012 =head2 _parse_[$name]_attr
1014 Allows you to customize parsing of subroutine attributes.
1016 sub myaction1 :Path TwoArgs { ... }
1018 sub _parse_TwoArgs_attr {
1019 my ( $self, $c, $name, $value ) = @_;
1020 # $self -> controller instance
1025 Please note that this feature does not let you actually assign new functions
1026 to actions via subroutine attributes, but is really more for creating useful
1027 aliases to existing core and extended attributes, and transforms based on
1028 existing information (like from configuration). Code for actually doing
1029 something meaningful with the subroutine attributes will be located in the
1030 L<Catalyst::Action> classes (or your subclasses), L<Catalyst::Dispatcher> and
1031 in subclasses of L<Catalyst::DispatchType>. Remember these methods only get
1032 called basically once when the application is starting, not per request!
1036 Catalyst Contributors, see Catalyst.pm
1040 This library is free software. You can redistribute it and/or modify
1041 it under the same terms as Perl itself.