]> Dogcows Code - chaz/p5-HTTP-AnyUA/blobdiff - lib/HTTP/AnyUA/Middleware.pm
add middleware
[chaz/p5-HTTP-AnyUA] / lib / HTTP / AnyUA / Middleware.pm
diff --git a/lib/HTTP/AnyUA/Middleware.pm b/lib/HTTP/AnyUA/Middleware.pm
new file mode 100644 (file)
index 0000000..21b6db8
--- /dev/null
@@ -0,0 +1,154 @@
+package HTTP::AnyUA::Middleware;
+# ABSTRACT: A base class for HTTP::AnyUA middleware
+
+=head1 SYNOPSIS
+
+    package HTTP::AnyUA::Middleware::MyMiddleware;
+
+    use parent 'HTTP::AnyUA::Middleware';
+
+    sub request {
+        my ($self, $method, $url, $args) = @_;
+
+        # Maybe do something with the request args here.
+
+        # Let backend handle the response:
+        my $response = $self->backend($method, $url, $args);
+
+        my $handle_response = sub {
+            my $response = shift;
+
+            # Maybe do something with the response here.
+
+            return $response;
+        };
+
+        if ($self->response_is_future) {
+            $response->transform(
+                done => $handle_response,
+                fail => $handle_response,
+            );
+        }
+        else {
+            $response = $handle_response->($response);
+        }
+
+        return $response;
+    }
+
+=head1 DESCRIPTION
+
+This module provides an interface for an L<HTTP::AnyUA> "middleware," which is a component that sits
+between an L<HTTP::AnyUA> object and the L<backend|HTTP::AnyUA::Backend> (which may in fact be
+another middleware).
+
+The easiest way to use middleware is to use L<HTTP::AnyUA/apply_middleware>.
+
+The middleware mechanism can be used to munge or react to requests and responses to and from the
+backend user agent. Middlewares are a completely optional part of L<HTTP::AnyUA>. They can be
+wrapped around each other to create multiple layers and interesting possibilities. The functionality
+provided by middleware may be alternative to features provided by some of the supported user agents,
+themselves, but implementing functionality on this layer makes it work for I<all> the user agents.
+
+=cut
+
+use warnings;
+use strict;
+
+our $VERSION = '9999.999'; # VERSION
+
+sub _croak { require Carp; Carp::croak(@_) }
+sub _usage { _croak("Usage: @_\n") }
+
+
+=method new
+
+    $middleware = HTTP::AnyUA::Middleware::MyMiddleware->new($backend);
+    $middleware = HTTP::AnyUA::Middleware::MyMiddleware->new($backend, %args);
+
+Construct a new middleware.
+
+=cut
+
+sub new {
+    my $class   = shift;
+    my $backend = shift or die 'Backend is required';
+    my $self = bless {backend => $backend}, $class;
+    $self->init(@_);
+    return $self;
+}
+
+=method init
+
+Called by the default constructor with the middleware arguments.
+
+This may be overridden by implementations instead of the constructor.
+
+=cut
+
+sub init {}
+
+=method wrap
+
+    $middleware = HTTP::AnyUA::Middleware::MyMiddleware->wrap($backend, %args);
+    $middleware->wrap($backend);
+
+Construct a new middleware or, when called on an instance, set a new backend on an existing
+middleware.
+
+=cut
+
+sub wrap {
+    my $self    = shift;
+    my $backend = shift or _usage($self . q{->wrap($backend, %args)});
+
+    if (ref $self) {
+        $self->{backend} = $backend;
+    }
+    else {
+        $self = $self->new($backend, @_);
+    }
+
+    return $self;
+}
+
+=method request
+
+    $response = $middleware->request($method => $url, \%options);
+
+Make a request, get a response.
+
+This should be overridden by implementations to do whatever they want with or to the request and/or
+response.
+
+=cut
+
+sub request { shift->backend->request(@_) }
+
+=attr backend
+
+Get the current backend that is wrapped.
+
+=cut
+
+sub backend { shift->{backend} }
+
+=attr ua
+
+Get the backend user agent.
+
+=cut
+
+sub ua { shift->backend->ua(@_) }
+
+=attr response_is_future
+
+Get whether or not responses are L<Future> objects. Default is whatever the backend returns.
+
+This may be overridden by implementations.
+
+=cut
+
+sub response_is_future { shift->backend->response_is_future(@_) }
+
+1;
This page took 0.019027 seconds and 4 git commands to generate.