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 )