Group
Extension

REST-Consumer/lib/REST/Consumer/HandlerInvocation.pm

package REST::Consumer::HandlerInvocation;

use strict;
use warnings;

use REST::Consumer::ResponseException;

# This is an object which is passed to a coderef in the handlers => {}
# hash. It represents an invocation of a particular response-code handler.
#
# Your code should never need to instantiate this class itself.
sub new {
	my ($class, %args) = @_;
	my $self = (bless {%args} => $class);
	$self->{debugger} ||= sub {};
	return $self;
}

# Here are elments of the public API:
# Magic values your code can return to change the execution flow:
sub default {
	my ($self) = @_;
	return REST::Consumer::HandlerFlow::Default->new;
}
sub retry {
	my ($self) = @_;
	return REST::Consumer::HandlerFlow::Retry->new(
		request => $self->request,
		response => $self->response,
		attempt => $self->attempt,
	);
}
sub fail {
	my ($self) = @_;
	return REST::Consumer::HandlerFlow::Fail->new(
		request => $self->request,
		response => $self->response,
		attempt => $self->attempt,
	);
}


# Accessors that can provide information to your handler:
sub request { shift->{request} }
sub response { shift->{response} }
sub attempt { shift->{attempt} } # e.g. attempt #2

# ->parsed_response throws an exception if the response is not parseable.
# You might want to ask whether ->response_parseable.
sub parsed_response {
	my ($self) = @_;
	$self->attempt_content_deserialization;
	unless ($self->{response_parseable}) {
		REST::Consumer::ResponseException->throw(
			request  => $self->{request},
			response => $self->{response},
			attempts => $self->{attempt},
		 );
	}
	return $self->{parsed_response};
}

# True iff the response was parseable.
sub response_parseable {
	my ($self) = @_;
	$self->attempt_content_deserialization;
	return $self->{response_parseable};
}

# This is never parsed, but it is decoded.
sub response_body {
	my ($self) = @_;
	$self->attempt_content_deserialization;
	return $self->{response_body};
}


# This is a private API. Do not invoke.
sub attempt_content_deserialization {
	my ($self) = @_;
	return if exists $self->{response_body};
	$self->{response_body} = $self->response->decoded_content();

	# parse response content, if present
	my $response_content;
	my $content_type = $self->response->header('Content-Type');
	if ($content_type && $content_type =~ m|.+/json|) {
		eval {
			$self->{parsed_response} = JSON::XS::decode_json($self->response->decoded_content() );
			$self->{response_parseable} = 1;
			1;
		} or do {
			# might or might not be an error.  e.g. if content is empty or is just a string
			$self->debug(sprintf("failed to parse json response: %s\n%s\n",
				$self->{response_body},
				$@,
			));
			$self->{response_parseable} = 0;
		};
	};
}

sub debug {
	shift->{debugger}->(@_);
}

# These are part of a private API. You should not instantiate them.
# Instead access them in the scope of a handler like so:
# 4xx => sub {
#   my ($h) = @_;
#   return $h->default; # or
#   return $h->retry;   # or
#   return $h->fail;
# }
package REST::Consumer::HandlerFlow::Base;
sub new {
	my ($self, %args) = @_;
	return bless {%args} => $self;
}

sub throw {
	my ($self) = @_;
	REST::Consumer::RequestException->throw(
		request  => $self->{request},
		response => $self->{response},
		attempts => $self->{attempt},
	 );
}


package REST::Consumer::HandlerFlow::Default;
use base qw(REST::Consumer::HandlerFlow::Base);
sub rest_consumer_should_default { 1 }

package REST::Consumer::HandlerFlow::Retry;
use base qw(REST::Consumer::HandlerFlow::Base);
sub rest_consumer_should_retry { 1 }

package REST::Consumer::HandlerFlow::Fail;
use base qw(REST::Consumer::HandlerFlow::Base);
sub rest_consumer_should_fail { 1 }

1;


Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.