summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist.ini1
-rw-r--r--lib/Plack/Client.pm115
-rw-r--r--lib/Plack/Client/Backend/http.pm28
-rw-r--r--lib/Plack/Client/Backend/psgi_local.pm41
-rw-r--r--t/01-basic.t5
-rw-r--r--t/02-inputs.t5
-rw-r--r--t/03-delayed-response.t5
-rw-r--r--t/04-streaming.t5
8 files changed, 143 insertions, 62 deletions
diff --git a/dist.ini b/dist.ini
index 532b9a4..9dc13d6 100644
--- a/dist.ini
+++ b/dist.ini
@@ -7,6 +7,7 @@ copyright_holder = Jesse Luehrs
dist = Plack-Client
[Prereqs]
+Class::Load = 0
HTTP::Request = 0
Plack = 0.9910
Plack::App::Proxy = 0
diff --git a/lib/Plack/Client.pm b/lib/Plack/Client.pm
index 588ef69..d05293b 100644
--- a/lib/Plack/Client.pm
+++ b/lib/Plack/Client.pm
@@ -3,10 +3,10 @@ use strict;
use warnings;
# ABSTRACT: abstract interface to remote web servers and local PSGI apps
+use Class::Load;
use HTTP::Message::PSGI;
use HTTP::Request;
-use Plack::App::Proxy;
-use Plack::Middleware::ContentLength;
+use Plack::Request;
use Plack::Response;
use Scalar::Util qw(blessed reftype);
@@ -76,39 +76,44 @@ sub new {
my $class = shift;
my %params = @_;
- die 'apps must be a hashref'
- if exists($params{apps}) && ref($params{apps}) ne 'HASH';
-
bless {
- apps => $params{apps},
- proxy => Plack::App::Proxy->new->to_app,
+ backend => {},
+ backend_args => \%params,
}, $class;
}
-=method apps
-
- my $apps = $client->apps;
-
-Returns the C<apps> hashref that was passed to the constructor.
+=method backend
=cut
-sub apps { shift->{apps} }
-sub _proxy { shift->{proxy} }
+sub backend {
+ my $self = shift;
+ my ($scheme) = @_;
+ $scheme = $self->_normalize_scheme($scheme);
+ return $self->{backend}->{$scheme};
+}
-=method app_for
+sub _set_backend {
+ my $self = shift;
+ my ($scheme, $backend) = @_;
+ $scheme = $self->_normalize_scheme($scheme);
+ $self->{backend}->{$scheme} = $backend;
+}
- my $app = $client->app_for('foo');
+sub _normalize_scheme {
+ my $self = shift;
-Returns the app corresponding to the given app name (or undef, if no such app
-exists).
+ my $scheme = blessed($_[0]) ? $_[0]->scheme : $_[0];
+ $scheme =~ s/-ssl$//;
+ $scheme = 'http' if $scheme eq 'https';
-=cut
+ return $scheme;
+}
-sub app_for {
+sub _backend_args {
my $self = shift;
- my ($for) = @_;
- return $self->apps->{$for};
+ my ($scheme) = @_;
+ return %{ $self->{backend_args}->{$scheme} || {} };
}
=method request
@@ -196,25 +201,21 @@ sub _http_request_to_env {
my $self = shift;
my ($req) = @_;
- my $scheme = $req->uri->scheme;
- my $app_name;
+ my $scheme = $req->uri->scheme;
+ my $authority = $req->uri->authority;
+
# hack around with this - psgi requires a host and port to exist, and
# for the scheme to be either http or https
- if ($scheme eq 'psgi-local') {
- $app_name = $req->uri->authority;
- $req->uri->scheme('http');
- $req->uri->host('Plack::Client');
- $req->uri->port(-1);
- }
- elsif ($scheme eq 'psgi-local-ssl') {
- $app_name = $req->uri->authority;
- $req->uri->scheme('https');
+ if ($scheme ne 'http' && $scheme ne 'https') {
+ if ($scheme =~ /-ssl$/) {
+ $req->uri->scheme('https');
+ }
+ else {
+ $req->uri->scheme('http');
+ }
$req->uri->host('Plack::Client');
$req->uri->port(-1);
}
- elsif ($scheme ne 'http' && $scheme ne 'https') {
- die 'Invalid URL scheme ' . $scheme;
- }
# work around http::message::psgi bug - see github issue 163 for plack
if (!$req->uri->path) {
@@ -227,8 +228,8 @@ sub _http_request_to_env {
$env->{CONTENT_LENGTH} ||= length($req->content);
$env->{'plack.client.url_scheme'} = $scheme;
- $env->{'plack.client.app_name'} = $app_name
- if defined $app_name;
+ $env->{'plack.client.authority'} = $authority
+ if defined $authority;
return $env;
}
@@ -239,30 +240,34 @@ sub _app_from_req {
my $uri = $req->uri;
my $scheme = $req->env->{'plack.client.url_scheme'} || $uri->scheme;
- my $app_name = $req->env->{'plack.client.app_name'};
- my $app;
- if ($scheme eq 'psgi-local') {
- if (!defined $app_name) {
- $app_name = $uri->authority;
- $app_name =~ s/(.*):.*/$1/; # in case a port was added at some point
- }
- $app = $self->app_for($app_name);
- die "Unknown app: $app_name" unless $app;
- $app = Plack::Middleware::ContentLength->wrap($app);
- }
- elsif ($scheme eq 'http' || $scheme eq 'https') {
- my $uri = $uri->clone;
- $uri->path('/');
- $req->env->{'plack.proxy.remote'} = $uri->as_string;
- $app = $self->_proxy;
- }
+ my $backend = $self->_scheme_to_backend($scheme);
+ my $app = $backend->app_from_req($req);
die "Couldn't find app" unless $app;
return $app;
}
+sub _scheme_to_backend {
+ my $self = shift;
+ my ($scheme) = @_;
+
+ $scheme = $self->_normalize_scheme($scheme);
+
+ my $backend = $self->backend($scheme);
+ return $backend if $backend;
+
+ (my $scheme_class = $scheme) =~ s/-/_/;
+ $scheme_class = "Plack::Client::Backend::$scheme_class";
+ Class::Load::load_class($scheme_class);
+
+ $backend = $scheme_class->new($self->_backend_args($scheme));
+ $self->_set_backend($scheme, $backend);
+
+ return $self->backend($scheme);
+}
+
sub _resolve_response {
my $self = shift;
my ($psgi_res) = @_;
diff --git a/lib/Plack/Client/Backend/http.pm b/lib/Plack/Client/Backend/http.pm
new file mode 100644
index 0000000..9982cd1
--- /dev/null
+++ b/lib/Plack/Client/Backend/http.pm
@@ -0,0 +1,28 @@
+package Plack::Client::Backend::http;
+use strict;
+use warnings;
+
+use Plack::App::Proxy;
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+
+ bless {
+ proxy => Plack::App::Proxy->new->to_app,
+ }, $class;
+}
+
+sub proxy { shift->{proxy} }
+
+sub app_from_req {
+ my $self = shift;
+ my ($req) = @_;
+
+ my $uri = $req->uri->clone;
+ $uri->path('/');
+ $req->env->{'plack.proxy.remote'} = $uri->as_string;
+ return $self->proxy;
+}
+
+1;
diff --git a/lib/Plack/Client/Backend/psgi_local.pm b/lib/Plack/Client/Backend/psgi_local.pm
new file mode 100644
index 0000000..212479e
--- /dev/null
+++ b/lib/Plack/Client/Backend/psgi_local.pm
@@ -0,0 +1,41 @@
+package Plack::Client::Backend::psgi_local;
+use strict;
+use warnings;
+
+use Plack::Middleware::ContentLength;
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+
+ die 'apps must be a hashref'
+ if exists($params{apps}) && ref($params{apps}) ne 'HASH';
+
+ bless {
+ apps => $params{apps},
+ }, $class;
+}
+
+sub apps { shift->{apps} }
+
+sub app_for {
+ my $self = shift;
+ my ($for) = @_;
+ return $self->apps->{$for};
+}
+
+sub app_from_req {
+ my $self = shift;
+ my ($req) = @_;
+
+ my $app_name = $req->env->{'plack.client.authority'};
+ if (!defined $app_name) {
+ $app_name = $req->uri->authority;
+ $app_name =~ s/(.*):.*/$1/; # in case a port was added at some point
+ }
+ my $app = $self->app_for($app_name);
+ die "Unknown app: $app_name" unless $app;
+ return Plack::Middleware::ContentLength->wrap($app);
+}
+
+1;
diff --git a/t/01-basic.t b/t/01-basic.t
index 0be56ac..6e185b4 100644
--- a/t/01-basic.t
+++ b/t/01-basic.t
@@ -35,11 +35,8 @@ test_tcp_plackup(
]
},
};
- my $client = Plack::Client->new(apps => $apps);
+ my $client = Plack::Client->new('psgi-local' => {apps => $apps});
isa_ok($client, 'Plack::Client');
- is($client->apps, $apps, "got apps back");
- is($client->app_for('foo'), $apps->{foo}, "got the right app");
- is($client->app_for('bar'), undef, "didn't get nonexistent app");
{
my $res = $client->get('psgi-local://foo/');
diff --git a/t/02-inputs.t b/t/02-inputs.t
index 04d5312..09e471c 100644
--- a/t/02-inputs.t
+++ b/t/02-inputs.t
@@ -48,7 +48,10 @@ test_tcp_plackup(
};
my $base_uri = 'psgi-local://foo';
- test_responses($base_uri, Plack::Client->new(apps => $apps));
+ test_responses(
+ $base_uri,
+ Plack::Client->new('psgi-local' => {apps => $apps})
+ );
}
sub test_responses {
diff --git a/t/03-delayed-response.t b/t/03-delayed-response.t
index 9d9b258..26d9037 100644
--- a/t/03-delayed-response.t
+++ b/t/03-delayed-response.t
@@ -51,7 +51,10 @@ test_tcp_plackup(
};
my $base_uri = 'psgi-local://foo';
- test_responses($base_uri, Plack::Client->new(apps => $apps));
+ test_responses(
+ $base_uri,
+ Plack::Client->new('psgi-local' => {apps => $apps})
+ );
}
sub test_responses {
diff --git a/t/04-streaming.t b/t/04-streaming.t
index a494681..17a42e6 100644
--- a/t/04-streaming.t
+++ b/t/04-streaming.t
@@ -52,7 +52,10 @@ test_tcp_plackup(
};
my $base_uri = 'psgi-local://foo';
- test_responses($base_uri, Plack::Client->new(apps => $apps));
+ test_responses(
+ $base_uri,
+ Plack::Client->new('psgi-local' => {apps => $apps})
+ );
}
sub test_responses {