Catalyst-TraitFor-Request-ContentNegotiationHelpers

 view release on metacpan or  search on metacpan

lib/Catalyst/ActionRole/ProvidesMedia.pm  view on Meta::CPAN

package Catalyst::ActionRole::ProvidesMedia;

use Moose::Role;
use Plack::MIME;
use Scalar::Util;
requires 'dispatch';

has 'media_actions' => (
  is=>'ro',
  required=>1,
  lazy=>1,
  builder=>'_build_media_actions');

  sub _build_media_actions {
    my $name = (my $self = shift)->name;
    my %media_actions = ();
    foreach my $action($self->class->meta->get_all_method_names) {
      my ($media_proto) = ($action=~m/^$name\_(.+)$/);
      next unless $media_proto;
      my $media = Plack::MIME->mime_type('.' . lc($media_proto)) ||
        ( $media_proto eq 'no_match' ? $media_proto : die "$media_proto not a MIME type" );
      $media_actions{$media} = $action;
    }

    return \%media_actions;
  }

sub forwards {
  my ($self, $ctx) = @_;

  Scalar::Util::weaken($ctx);
  my %media_actions = %{$self->media_actions};
  unless(exists $media_actions{no_match}) {
    $media_actions{no_match} = sub {
      my ($req, %callbacks) = @_;
      $ctx->res->status(406);
      $ctx->res->content_type('text/plain');
      my $allowed = join(',',(keys %callbacks)); 
      $ctx->res->body("You requested a media type we don't support.  Acceptable types are: $allowed");
    };
  }

  my @forwards = map {
    my $action = $media_actions{$_};
    $_ => $_ eq 'no_match' ?
      sub { $ctx->forward($action, \%media_actions) } :
      sub { $ctx->forward($action) };
  } (keys %media_actions);

  return @forwards;
}

around 'dispatch', sub {
  my ($orig, $self, $ctx, @rest) = @_;
  my $return = $self->$orig($ctx, @rest);
  $ctx->req->on_best_media_type($self->forwards($ctx));
  return $return;
};

1;

=head1 NAME

Catalyst::ActionRole::ProvidesMedia - Delegate actions based on best mediatype match

=head1 SYNOPSIS

    package MyApp;
    use Catalyst;
  
    MyApp->request_class_traits(['Catalyst::TraitFor::Request::ContentNegotiationHelpers']);
    MyApp->setup;

    package MyApp::Controller::Example;

    use Moose;
    use MooseX::MethodAttributes;

    extends 'Catalyst::Controller';

    sub myaction :Chained(/) Does('ProvidesMedia') CaptureArgs(0) {
      my ($self, $c) = @_;
    }

      # Executed if the request accept header like prefers and accepts
      # type 'application/json'.
      sub myaction_JSON :Action { }

      # Executed if the request accept header like prefers and accepts
      # type 'text/html'.
      sub myaction_HTML :Action { }

      # Executed if none of the above types are accepted by the incoming
      # request accept header.

      sub myaction_no_match :Action {
        my ($self, $c, $matches) = @_;
        



( run in 1.000 second using v1.01-cache-2.11-cpan-39bf76dae61 )