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 <lxp@cpan.org>

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.

