Catalyst-Plugin-ResponseFrom

 view release on metacpan or  search on metacpan

lib/Catalyst/Plugin/ResponseFrom.pm  view on Meta::CPAN

  if ($path =~ s/^(.*?)\@//) {
    my $basic = $1;
    unshift @rest, 'Authorization:', 'Basic '.MIME::Base64::encode($basic);
  }
 
  my $request = HTTP::Request->new($method => $path);
 
  my @params;
 
  while (my ($header, $value) = splice(@rest, 0, 2)) {
    unless ($header =~ s/:$//) {
      push @params, $header, $value;
    }
    $header =~ s/_/-/g;
    if ($header eq 'Content') {
      $request->content($value);
    } else {
      $request->headers->push_header($header, $value);
    }
  }
 
  if (($method eq 'POST' or $method eq 'PUT') and @params) {
    my $content = do {
      my $url = URI->new('http:');
      $url->query_form(@params);
      $url->query;
    };
    $request->header('Content-Type' => 'application/x-www-form-urlencoded');
    $request->header('Content-Length' => length($content));
    $request->content($content);
  }
 
  return $request;
};

sub psgi_response_from {
  my $self = shift;
  my $http_request = $self->$_request_spec_to_http_request(@_);
  my $psgi_env = HTTP::Message::PSGI::req_to_psgi($http_request);
  return my $psgi_response = $self->psgi_app->($psgi_env);
}

*response_from = \&http_response_from;
sub http_response_from {
  my $self = shift;
  my $psgi_response = $self->psgi_response_from(@_);
  return my $http_response = HTTP::Message::PSGI::res_from_psgi($psgi_response);
}

sub redispatch_to {
  my $self = shift;
  my $psgi_response = $self->psgi_response_from(@_);
  $self->res->from_psgi_response($psgi_response);
  $self->detach;
}

1;

=head1 NAME

Catalyst::Plugin::ResponseFrom - Use the response of a public endpoint.

=head1 SYNOPSIS

    package MyApp;
    use Catalyst 'ResponseFrom';

    MyApp->setup;

    package MyApp::Controller::Example;

    use Moose;
    use MooseX::MethodAttributes;
    use HTTP::Request::Common;

    extends 'Catalyst::Controller';

    sub as_http_request :Local {
      my ($self, $c) = @_;
      $c->redispatch_to(GET $c->uri_for($self->action_for('target')));
      # For simple GETs you can just use $c->uri_for style params like:
      $c->redispatch_to($self->action_for('target'));
    }

    sub as_spec :Local {
      my ($self, $c) = @_;
      $c->redispatch_to('GET' => $c->uri_for($self->action_for('target')));
    }

    sub collect_response :Local {
      my ($self, $c) = @_;
      my $http_response = $c->http_response_from(GET => $c->uri_for($self->action_for('target')));
    }

    sub target :Local {
      my ($self, $c) = @_;
      $c->response->content_type('text/plain');
      $c->response->body("This is the target action");
    }

=head1 DESCRIPTION

L<Catalyst> allows you to forward to a private named actions, but there is no
built in method to 'forward' to a public URL.  You might want to do this rather
than (for example) issue a redirect.

Additionally there is no 'subrequest' like feature (and L<Catalyst::Plugin::Subrequest>
uses internal hacks to function).  There maye be cases, such as in testing, where
it would be great to be able to issue a public URL request and collect the response.

This plugin is an attempt to give you these features in a clean manner that does not
rely on internal L<Catalyst> details that are subject to change.  However you must be
using a more modern version of L<Catalyst> (the current requirement is 5.90060).

=head1 METHODS

This plugin adds the following methods to your L<Catalyst> application.  All methods
share the same function signature (this approach and following documentation 'borrowed'
from L<Web::Simple>):

    my $psgi_response = $app->http_response_from(GET => '/' => %headers);



( run in 0.532 second using v1.01-cache-2.11-cpan-2398b32b56e )