AnyEvent-CouchDB

 view release on metacpan or  search on metacpan

lib/AnyEvent/CouchDB.pm  view on Meta::CPAN

use AnyEvent::CouchDB::Database;
use AnyEvent::CouchDB::Exceptions;
use URI;
use URI::Escape;
use File::Basename;
use MIME::Base64;

use Exporter;
use base 'Exporter';

our @EXPORT = qw(couch couchdb);

# exception class shortcuts
our $HTTPError = "AnyEvent::CouchDB::Exception::HTTPError";
our $JSONError = "AnyEvent::CouchDB::Exception::JSONError";

# default JSON encoder
our $default_json = JSON->new->allow_nonref->utf8;

# arbitrary uri support
sub _build_headers {
  my ( $self, $options ) = @_;
  my $headers = $options->{headers};
  if ( ref($headers) ne 'HASH' ) {
    $headers = {};
  }

  # should probably move $options->{type} to $options->{headers}
  if ( exists $options->{type} ) {
    $headers->{'Content-Type'} = $options->{type};
  }
  elsif ( !exists $headers->{'Content-Type'} ) {
    $headers->{'Content-Type'} = 'application/json';
  }

  if ( exists $self->{http_auth} ) {
    $headers->{'Authorization'} = $self->{http_auth};
  }

  return $headers;
}

# return a condvar and callback 
#
# - The condvar is what most of our methods return.
#   You can call recv on them to get data back, or
#   you can call cb on them to assign an asynchronous callback to
#   run WHEN the data comes back
#
# - The callback is the code that handles the 
#   generic part of every CouchDB response.  This is given
#   to AnyEvent::HTTP.
#   
sub cvcb {
  my ($options, $status, $json) = @_;
  $status ||= 200;
  $json   ||= $default_json;
  my $cv = AE::cv;
  AE::now_update();

  # default success handler sends back decoded json response
  my $success = sub {
    my ($resp) = @_;
    $options->{success}->(@_) if ($options->{success});
    $cv->send($resp);
  };

  # default error handler croaks w/ http headers and response
  my $error = sub {
    my ($headers, $response) = @_;
    $options->{error}->(@_) if ($options->{error});
    $cv->croak(
      $HTTPError->new(
        message  => sprintf("%s - %s - %s", $headers->{Status}, $headers->{Reason}, $headers->{URL}),
        headers  => $headers,
        body     => $response
      )
    );
  };

  my $cb = sub {
    my ($body, $headers) = @_;
    my $response;
    eval { $response = $json->decode($body); };
    $cv->croak(
      $JSONError->new(
        message  => $@,
        headers  => $headers,
        body     => $body
      )
    ) if ($@);
    if ($headers->{Status} >= $status and $headers->{Status} < 400) {
      $success->($response);
    } else {
      $error->($headers, $body);
    }
  };
  ($cv, $cb);
}

sub couch {
  AnyEvent::CouchDB->new(@_);
}

sub couchdb {
  my $db = shift;
  if ($db =~ /^https?:/) {
    $db .= '/' if ($db !~ /\/$/);
    my $uri  = URI->new($db);
    my $name = basename($db);
    AnyEvent::CouchDB::Database->new($name, $uri);
  } else {
    AnyEvent::CouchDB->new->db($db);
  }
}

sub new {
  my ($class, $uri) = @_;
  $uri ||= 'http://localhost:5984/';
  my $self = bless { uri => URI->new($uri) } => $class;
  if (my $userinfo = $self->{uri}->userinfo) {



( run in 3.091 seconds using v1.01-cache-2.11-cpan-ecdf5575e8d )