proxy object for the PSGI writer
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Controller.pm
index 1594172..02db77a 100644 (file)
@@ -9,7 +9,10 @@ use List::Util qw/first/;
 use List::MoreUtils qw/uniq/;
 use namespace::clean -except => 'meta';
 
-BEGIN { extends qw/Catalyst::Component MooseX::MethodAttributes::Inheritable/; }
+BEGIN {
+    extends qw/Catalyst::Component/;
+    with qw/MooseX::MethodAttributes::Role::AttrContainer::Inheritable/;
+}
 
 use MooseX::MethodAttributes;
 use Catalyst::Exception;
@@ -117,7 +120,7 @@ for more info about how Catalyst dispatches to actions.
 =cut
 
 #I think both of these could be attributes. doesn't really seem like they need
-#to ble class data. i think that attributes +default would work just fine
+#to be class data. i think that attributes +default would work just fine
 __PACKAGE__->mk_classdata($_) for qw/_dispatch_steps _action_class _action_role_prefix/;
 
 __PACKAGE__->_dispatch_steps( [qw/_BEGIN _AUTO _ACTION/] );
@@ -317,7 +320,7 @@ sub action_class {
         ? $args{attributes}{ActionClass}[0]
         : $self->_action_class);
 
-    Class::MOP::load_class($class);
+    load_class($class);
     return $class;
 }
 
@@ -365,7 +368,11 @@ sub gather_default_action_roles {
   my @roles = ();
   push @roles, 'Catalyst::ActionRole::HTTPMethods'
     if $args{attributes}->{Method};
-  return @roles;
+
+  push @roles, 'Catalyst::ActionRole::ConsumesContent'
+    if $args{attributes}->{Consumes};
+
+    return @roles;
 }
 
 sub _parse_attrs {
@@ -649,7 +656,7 @@ overridden from the "namespace" config key.
 
 =head2 $self->path_prefix($c)
 
-Returns the default path prefix for :PathPrefix, :Local, :LocalRegex and
+Returns the default path prefix for :PathPrefix, :Local and
 relative :Path actions in this component. Defaults to the action_namespace or
 can be overridden from the "path" config key.
 
@@ -705,7 +712,7 @@ similar to how annotations work in other languages you might have heard of.
 Generally L<Catalyst> uses these to influence how the dispatcher sees your
 action and when it will run it in response to an incoming request.  They can
 also be used for other things.  Here's a summary, but you should refer to the
-liked manual page for additional help.
+linked manual page for additional help.
 
 =head2 Global
 
@@ -740,18 +747,20 @@ Handle various types of paths:
     ...
 
     sub myaction1 :Path { ... }  # -> /baz
-    sub myaction2 :Path('foo') { ... } # -> /baz/bar
+    sub myaction2 :Path('foo') { ... } # -> /baz/foo
     sub myaction2 :Path('/bar') { ... } # -> /bar
   }
 
-This is a general toolbox for attaching your action to a give path.
+This is a general toolbox for attaching your action to a given path.
 
 
 =head2 Regex
 
 =head2 Regexp
 
-Status: Deprecated.  Use Chained methods or other techniques
+B<Status: Deprecated.>  Use Chained methods or other techniques.
+If you really depend on this, install the standalone 
+L<Catalyst::DispatchType::Regex> distribution.
 
 A global way to match a give regular expression in the incoming request path.
 
@@ -759,6 +768,10 @@ A global way to match a give regular expression in the incoming request path.
 
 =head2 LocalRegexp
 
+B<Status: Deprecated.>  Use Chained methods or other techniques.
+If you really depend on this, install the standalone 
+L<Catalyst::DispatchType::Regex> distribution.
+
 Like L</Regex> but scoped under the namespace of the containing controller
 
 =head2 Chained 
@@ -821,6 +834,61 @@ When used with L</Path> indicates the number of arguments expected in
 the path.  However if no Args value is set, assumed to 'slurp' all
 remaining path pars under this namespace.
 
+=head2 Consumes('...')
+
+Matches the current action against the content-type of the request.  Typically
+this is used when the request is a POST or PUT and you want to restrict the
+submitted content type.  For example, you might have an HTML for that either
+returns classic url encoded form data, or JSON when Javascript is enabled.  In
+this case you may wish to match either incoming type to one of two different
+actions, for properly processing.
+
+Examples:
+
+    sub is_json       : Chained('start') Consumes('application/json') { ... }
+    sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
+    sub is_multipart  : Chained('start') Consumes('multipart/form-data') { ... }
+
+To reduce boilerplate, we include the following content type shortcuts:
+
+Examples
+
+      sub is_json       : Chained('start') Consume(JSON) { ... }
+      sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
+      sub is_multipart  : Chained('start') Consumes(Multipart) { ... }
+
+You may specify more than one match:
+
+      sub is_more_than_one
+        : Chained('start')
+        : Consumes('application/x-www-form-urlencoded')
+        : Consumes('multipart/form-data')
+
+      sub is_more_than_one
+        : Chained('start')
+        : Consumes(UrlEncoded)
+        : Consumes(Multipart)
+
+Since it is a common case the shortcut C<HTMLForm> matches both
+'application/x-www-form-urlencoded' and 'multipart/form-data'.  Here's the full
+list of available shortcuts:
+
+    JSON => 'application/json',
+    JS => 'application/javascript',
+    PERL => 'application/perl',
+    HTML => 'text/html',
+    XML => 'text/XML',
+    Plain => 'text/plain',
+    UrlEncoded => 'application/x-www-form-urlencoded',
+    Multipart => 'multipart/form-data',
+    HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
+
+Please keep in mind that when dispatching, L<Catalyst> will match the first most
+relevant case, so if you use the C<Consumes> attribute, you should place your
+most accurate matches early in the Chain, and your 'catchall' actions last.
+
+See L<Catalyst::ActionRole::ConsumesContent> for more.
+
 =head1 OPTIONAL METHODS
 
 =head2 _parse_[$name]_attr