NAME
   HTTP::Response::Switch - handle many HTTP response possibilities

VERSION
   This module is part of distribution HTTP-Response-Switch v1.0.0.

   This distribution's version numbering follows the conventions defined at
   semver.org <http://semver.org/>.

SYNOPSIS
   Define a "dispatcher" for the application code to use directly:

       package MyProject::WebResponses;
       use Moose;
       with 'HTTP::Response::Switch';

       # All of the handlers are defined under this namespace.
       sub handler_namespace { 'MyProject::WebResponse' }

       # Always resort to these handlers before giving up on a response.
       sub default_handlers { qw( ConfirmAction LoginForm ) }

       # Throw an exception of this class if the response can't be handled
       # by any of the specified handlers.
       sub default_exception { 'MyProject::Error::BadWebResponse' }

       # Load all of the handlers at compile-time (recommended).
       __PACKAGE__->load_handlers;

   Then, in code that actually talks to the web server:

       my $http_response = WWW::Mechanize->new->post( URL, USER_DATA );

       # Either the right data will be returned, or there was a problem
       # with some user data, or the session got logged out, or the system
       # is down for maintenance, or something entirely unanticipated will
       # happen.  Whatever the case, do the right thing.
       use TryCatch;
       try {
           my @expected_data = MyProject::WebResponses->handle(
               $http_response,
               qw{ RawDataPage RawDataForm },
           );
           return SOMETHING_BUILT_FROM( @expected_data );
       }
       catch (MyProject::Error::NeedConfirmation $e) {
           CLICK_YES;
           TRY_AGAIN;
       }
       catch (MyProject::Error::NotLoggedIn $e) {
           LOG_BACK_IN;
           TRY_AGAIN;
       }

       # Don't catch all possible exceptions here; let calling code decide
       # what to do in some cases.

   Also define each handler:

       package MyProject::WebResponse::ConfirmAction;  ...
       package MyProject::WebResponse::LoginForm;      ...
       package MyProject::WebResponse::RawDataPage;    ...
       package MyProject::WebResponse::RawDataForm;    ...

   See "SYNOPSIS" in HTTP::Response::Switch::Handler for example handler
   definitions.

DESCRIPTION
   Sometimes the only possible way to communicate with an online service is
   through a web application intended for human consumption--dealing with
   cookies, forms and parsing of HTML, perhaps with the help of
   WWW::Mechanize and Web::Scraper.

   When automating such a web application, it may be unsafe to assume that
   a specific request will always trigger a specific response. For example,
   requesting bank transactions from an Internet Banking server could
   result in a response containing:

   1   a CSV file of bank transactions (the "expected" response);

   2   an HTML page indicating an input error and presenting a form;

   3   an HTML page indicating that the session has been terminated;

   4   an HTML page indicating an Internal Server Error; or

   5   something else entirely unanticipated.

   Some of those "unexpected" or "undesired" responses may require special
   behaviour, in which case it isn't appropriate to simply "die" on such
   responses. Moreover, some of those responses could potentially occur on
   any communication with the web application, creating the need to test
   for them at every single point that the web server is contacted.

   This distribution aims to abstract away some of the code verbosity that
   would be required for this by providing Moose roles for:

   1.  "Handler" classes, which look at a specific HTTP::Response object
       with a single concern in mind and either return structured data,
       throw an exception, or indicate that they don't know how to handle
       that specific response.

   2.  A "dispatcher" class which takes an HTTP::Response object and passes
       it through a chain of the aforementioned "handler" classes until one
       of them returns structured data or throws an exception; or, if none
       of them do, indicates that that specific response truly is
       "unexpected."

USAGE
   Refer to the "SYNOPSIS" above. Further information on configuring a
   "dispatcher" class follows in subsequent sections. See
   HTTP::Response::Switch::Handler for further information on writing
   "handler" classes.

METHODS TO DEFINE IN CONSUMING CLASSES
   These methods can be defined in a consuming class in order to customise
   functionality provided by the role. Some of these methods must be
   defined in order for the consuming class to work.

 handler_namespace
       sub handler_namespace { 'MyProject::WebResponse' }

   The namespace under which handler classes are to be found. This method
   must be defined in every consuming class.

 default_handlers
       sub default_handlers { qw( LoginForm ) }

   A list of handler classes (minus the "handler_namespace") that should be
   asked to process an HTTP::Response if no other handler accepts the
   response first. If not defined in the consuming class, an empty list is
   assumed.

 default_exception
       sub default_exception { 'MyProject::Error::BadWebResponse' }

   The exception class to throw if, during a call to "handle" by external
   code, no handlers accept the HTTP::Response in question. The instance of
   this class will be passed the HTTP response object when created, via
   parameter "response".

   If not defined in the consuming class, the default behaviour in this
   situation is to just "die" with the message "unexpected HTTP response".

   The Throwable distribution is suggested for building object-oriented
   exception classes.

METHODS AVAILABLE FROM WITHIN CONSUMING CLASSES
   These methods are intended only to be called on a consuming class by
   that class itself, and not by code external to the class.

 load_handlers
       __PACKAGE__->load_handlers;

   Use Module::Find to locate all of the modules under the
   "handler_namespace" and load them into memory.

   The handler modules must be loaded into memory before the first call to
   "handle" occurs. Loading them at compile time is recommended; to do
   this, call "load_handlers" within the consuming class in the manner
   shown above, outside all "sub" definitions.

METHODS AVAILABLE TO CALLERS OF CONSUMING CLASSES
   These methods are intended to be called directly on a consuming class by
   code external to the class.

 handle
       my @ret = MyDispatcher->handle( $http_response, @handlers );

   Pass the HTTP::Response object in $http_response to each handler class
   defined in @handlers (if any, and minus the "handler_namespace"), then
   to each of the "default_handlers", until one of the handlers accepts the
   response for handling and either returns appropriate data or throws an
   appropriate exception.

   If none of the handlers accept this $http_response, throw the
   "default_exception".

   All of the handler classes are assumed to have been loaded into memory
   *before* this method is first called. See "load_handlers".

SEE ALSO
   *   HTTP::Response::Switch::Handler

SUPPORT
 Bugs / Feature Requests
   Please report any bugs or feature requests by email to
   "bug-http-response-switch at rt.cpan.org", or through the web interface
   at
   <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=HTTP-Response-Switch>.
   You will be automatically notified of any progress on the request by the
   system.

 Source Code
   The source code for this distribution is available online in a Git
   <http://git-scm.com/> repository. Please feel welcome to contribute
   patches.

   <https://github.com/lx/perl5-HTTP-Response-Switch>

     git clone git://github.com/lx/perl5-HTTP-Response-Switch

AUTHOR
   Alex Peters <[email protected]>

COPYRIGHT AND LICENSE
   This software is copyright (c) 2013 by Alex Peters.

   This is free software; you can redistribute it and/or modify it under
   the same terms as the Perl 5 programming language system itself.

   The full text of the license can be found in the 'LICENSE' file included
   with this distribution.