summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2011-01-12 11:44:09 -0600
committerJesse Luehrs <doy@tozt.net>2011-01-12 11:44:09 -0600
commit9970a68dbb108d36b16595d26b827a7d63223155 (patch)
treefc29554cd9c21e644e4f0b88b5c41aafdc2ab216
parent887ef01b958d7c45fc7ea29d9b0ff570a54505dc (diff)
downloadplack-client-9970a68dbb108d36b16595d26b827a7d63223155.tar.gz
plack-client-9970a68dbb108d36b16595d26b827a7d63223155.zip
add Plack::Client::Backend as a base class
-rw-r--r--lib/Plack/Client.pm30
-rw-r--r--lib/Plack/Client/Backend.pm66
-rw-r--r--lib/Plack/Client/Backend/http.pm10
-rw-r--r--lib/Plack/Client/Backend/psgi_local.pm9
4 files changed, 94 insertions, 21 deletions
diff --git a/lib/Plack/Client.pm b/lib/Plack/Client.pm
index 813351c..1ed096a 100644
--- a/lib/Plack/Client.pm
+++ b/lib/Plack/Client.pm
@@ -69,10 +69,13 @@ appropriate apps based on the request.
)
Constructor. Takes a hash of arguments, where keys are URL schemas, and values
-are backends which handle those schemas. Hashref and arrayref values are also
-valid, and will be dereferenced and passed to the constructor of the default
-backend for that scheme (the class C<Plack::Client::Backend::$scheme>, where
-C<$scheme> has dashes replaced by underscores).
+are backends which handle those schemas. Backends are really just coderefs
+which receive a L<Plack::Request> and return a PSGI application coderef, but
+see L<Plack::Client::Backend> for a more structured way to define these.
+Hashref and arrayref values are also valid, and will be dereferenced and passed
+to the constructor of the default backend for that scheme (the class
+C<Plack::Client::Backend::$scheme>, where C<$scheme> has dashes replaced by
+underscores).
=cut
@@ -83,27 +86,26 @@ sub new {
my %backends;
for my $scheme (keys %params) {
my $backend = $params{$scheme};
- if (blessed($backend)) {
- croak "Backends must support the app_from_request method"
- unless $backend->can('app_from_request');
+ if ((blessed($backend) || '') eq 'Plack::Client::Backend') {
+ $backends{$scheme} = $backend->as_code;
+ }
+ elsif (reftype($backend) eq 'CODE') {
$backends{$scheme} = $backend;
}
elsif (ref($backend)) {
(my $normal_scheme = $scheme) =~ s/-/_/g;
my $backend_class = "Plack::Client::Backend::$normal_scheme";
Class::Load::load_class($backend_class);
- croak "Backends must support the app_from_request method"
- unless $backend_class->can('app_from_request');
- croak "Backend classes must have a constructor"
- unless $backend_class->can('new');
+ croak "Backend classes must inherit from Plack::Client::Backend"
+ unless $backend_class->isa('Plack::Client::Backend');
$backends{$scheme} = $backend_class->new(
reftype($backend) eq 'HASH' ? %$backend
: reftype($backend) eq 'ARRAY' ? @$backend
: $$backend
- );
+ )->as_code;
}
else {
- croak 'XXX';
+ croak "Backends must be a coderef or a Plack::Client::Backend instance";
}
}
@@ -265,7 +267,7 @@ sub _app_from_request {
my $uri = $req->env->{'plack.client.original_uri'} || $req->uri;
my $backend = $self->backend($uri);
- my $app = $backend->app_from_request($req);
+ my $app = $backend->($req);
croak "Couldn't find app" unless $app;
diff --git a/lib/Plack/Client/Backend.pm b/lib/Plack/Client/Backend.pm
new file mode 100644
index 0000000..3ba7771
--- /dev/null
+++ b/lib/Plack/Client/Backend.pm
@@ -0,0 +1,66 @@
+package Plack::Client::Backend;
+use strict;
+use warnings;
+# ABSTRACT: turns a Plack::Request into a PSGI app
+
+use Carp;
+use Scalar::Util qw(weaken);
+
+use overload '&{}' => sub { shift->as_code(@_) }, fallback => 1;
+
+=head1 SYNOPSIS
+
+ package My::Backend;
+ use base 'Plack::Client::Backend';
+
+ sub app_from_request {
+ my $self = shift;
+ my ($req) = @_;
+ return sub { ... }
+ }
+
+=head1 DESCRIPTION
+
+This is a base class for L<Plack::Client> backends. These backends are handlers
+for a particular URL scheme, and translate a L<Plack::Request> instance into a
+PSGI application coderef.
+
+=cut
+
+=method new
+
+Creates a new backend instance. Takes no parameters by default, but may be
+overridden in subclasses.
+
+=cut
+
+sub new {
+ my $class = shift;
+ bless {}, $class;
+}
+
+=method app_from_request
+
+This method is called with an argument of a L<Plack::Request> object, and
+should return a PSGI application coderef. The Plack::Request object it receives
+contains the actual env hash that will be passed to the application, so
+backends can modify that too, if they need to.
+
+=cut
+
+sub app_from_request {
+ croak "Backends must implement app_from_request";
+}
+
+=method as_code
+
+Returns a coderef which will call L</app_from_request> as a method.
+
+=cut
+
+sub as_code {
+ my $self = shift;
+ return sub { $self->app_from_request(@_) };
+}
+
+1;
diff --git a/lib/Plack/Client/Backend/http.pm b/lib/Plack/Client/Backend/http.pm
index e443385..542c2ce 100644
--- a/lib/Plack/Client/Backend/http.pm
+++ b/lib/Plack/Client/Backend/http.pm
@@ -5,6 +5,8 @@ use warnings;
use Plack::App::Proxy;
+use base 'Plack::Client::Backend';
+
=head1 SYNOPSIS
Plack::Client->new(
@@ -30,11 +32,11 @@ Constructor. Takes no arguments.
sub new {
my $class = shift;
- my %params = @_;
+ my $self = $class->SUPER::new(@_);
+
+ $self->{proxy} = Plack::App::Proxy->new->to_app;
- bless {
- proxy => Plack::App::Proxy->new->to_app,
- }, $class;
+ return $self;
}
sub _proxy { shift->{proxy} }
diff --git a/lib/Plack/Client/Backend/psgi_local.pm b/lib/Plack/Client/Backend/psgi_local.pm
index 1da572b..7bb9bcc 100644
--- a/lib/Plack/Client/Backend/psgi_local.pm
+++ b/lib/Plack/Client/Backend/psgi_local.pm
@@ -6,6 +6,8 @@ use warnings;
use Carp;
use Plack::Middleware::ContentLength;
+use base 'Plack::Client::Backend';
+
=head1 SYNOPSIS
Plack::Client->new(
@@ -43,13 +45,14 @@ A mapping of local app names to PSGI app coderefs.
sub new {
my $class = shift;
my %params = @_;
+ my $self = $class->SUPER::new(@_);
croak 'apps must be a hashref'
if ref($params{apps}) ne 'HASH';
- bless {
- apps => $params{apps},
- }, $class;
+ $self->{apps} = $params{apps};
+
+ return $self;
}
sub _apps { shift->{apps} }