package WebAPI::DBIC::Resource::Role::ItemInvoke;
$WebAPI::DBIC::Resource::Role::ItemInvoke::VERSION = '0.004002';
use Scalar::Util qw(blessed);
use Moo::Role;
requires 'decode_json';
requires 'encode_json';
requires 'render_item_as_plain_hash';
requires 'throwable';
requires 'item';
has method => (
is => 'ro',
required => 1,
);
sub post_is_create { return 0 }
around 'allowed_methods' => sub {
return [ qw(POST) ];
};
sub process_post {
my $self = shift;
# Here's we're calling a method on the item as a simple generic behaviour.
# This is very limited because, for example, the method has no knowledge
# that it's being called inside a web service, thus no way to do redirects
# or provide HTTP specific rich-exceptions.
# If anything more sophisticated is required then it should be implemented
# as a specific resource class for the method (or perhaps a role if there's
# a set of methods that require similar behaviour).
# The POST body content provides a data structure containing the method arguments
# { args => [ (@_) ] }
$self->throwable->throw_bad_request(415, errors => "Request content-type not application/json")
unless $self->request->header('Content-Type') =~ 'application/.*?json';
my $invoke_body_data = $self->decode_json($self->request->content);
$self->throwable->throw_bad_request(400, errors => "Request content not a JSON hash")
unless ref $invoke_body_data eq 'HASH';
my @method_args;
if (my $args = delete $invoke_body_data->{args}) {
$self->throwable->throw_bad_request(400, errors => "The args must be an array")
if ref $args ne 'ARRAY';
@method_args = @$args;
}
$self->throwable->throw_bad_request(400, errors => "Unknown attributes: @{[ keys %$invoke_body_data ]}")
if keys %$invoke_body_data;
my $method_name = $self->method;
# the method is expected to throw an exception on error.
my $result_raw = $self->item->$method_name(@method_args);
my $result_rendered;
# return a DBIC resultset as array of hashes of ALL records (no paging)
if (blessed($result_raw) && $result_raw->isa('DBIx::Class::ResultSet')) {
$result_rendered = [ map { $self->render_item_as_plain_hash($_) } $result_raw->all ];
}
# return a DBIC result row as a hash
elsif (blessed($result_raw) && $result_raw->isa('DBIx::Class::Row')) {
$result_rendered = $self->render_item_as_plain_hash($result_raw);
}
# return anything else as raw JSON wrapped in a hash
else {
# we shouldn't get an object here, but if we do then we
# stringify it here to avoid exposing the guts
$result_rendered = { result => (blessed $result_raw) ? "$result_raw" : $result_raw };
}
$self->response->body( $self->encode_json($result_rendered) );
return 200;
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
WebAPI::DBIC::Resource::Role::ItemInvoke
=head1 VERSION
version 0.004002
=head1 NAME
WebAPI::DBIC::Resource::Role::ItemInvoke - methods for resources representing method calls on item resources
=head1 AUTHOR
Tim Bunce <[email protected]>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2015 by Tim Bunce.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut