API-Docker

 view release on metacpan or  search on metacpan

lib/API/Docker/Error/HTTP.pm  view on Meta::CPAN

package API::Docker::Error::HTTP;
# ABSTRACT: Error status returned by the Docker Engine on the status line
our $VERSION = '0.004';
use Moo;
# namespace::clean has to come BEFORE "use overload" here, not after it as
# everywhere else in this distribution -- same reason as in
# API::Docker::Error::Stream. It sweeps the symbols `overload` installs --
# the `("" ` slot among them -- so with the two lines in the house order the
# class ends up not overloaded at all and stringifies as
# API::Docker::Error::HTTP=HASH(0x...). Nothing dies when that happens: every
# caller that only inspects $@ as a string silently starts seeing a reference
# address instead of the reason, and this is the exception every resource
# method in the distribution can raise. Measured, not assumed:
# overload::Overloaded($err) is false with the lines swapped.
use namespace::clean;
use overload
  '""'     => sub { $_[0]->as_string },
  'bool'   => sub { 1 },
  fallback => 1;


has message => (
  is       => 'ro',
  required => 1,
);


has location => (
  is      => 'ro',
  default => sub { '' },
);


has status => (
  is       => 'ro',
  required => 1,
);


has reason => (
  is      => 'ro',
  default => sub { '' },
);


has body => (
  is      => 'ro',
  default => sub { '' },
);


has data => (
  is => 'ro',
);


sub as_string { $_[0]->message . $_[0]->location }



1;

__END__

=pod

=encoding UTF-8

=head1 NAME

API::Docker::Error::HTTP - Error status returned by the Docker Engine on the status line

=head1 VERSION

version 0.004

=head1 SYNOPSIS

    eval { $docker->containers->kill($id) };
    if (my $err = $@) {
        # Behaves exactly like the string it replaces ...
        warn "kill failed: $err";

        # ... and carries the status code, so 404 and 409 are told apart
        # without matching on prose the engine is free to change.
        if (ref $err && $err->isa('API::Docker::Error::HTTP')) {
            return    if $err->status == 404;   # already gone
            sleep 1   if $err->status == 409;   # wrong state, retry
        }
    }

=head1 DESCRIPTION

L<API::Docker::Role::HTTP> croaks with an object of this class whenever the
engine answers a request with a status of 400 or above.

The reason it exists is that the croak B<text> is not an interface. What the
engine puts in the error body is engine-specific prose: a kill against a
stopped container answers 409 with C<can only kill running containers. E<lt>idE<gt> is
in state stopped: container state improper> on rootless Podman 5.4.2, while
Docker's own example for the same case is C<Container E<lt>idE<gt> is not running> --
a different body shape and entirely different wording. A caller that has to
tell "no such container" from "wrong state" apart had no choice but to match
that prose. L</status> is the same distinction as a number the engine
documents.

=head2 It is still the string it replaces



( run in 1.840 second using v1.01-cache-2.11-cpan-6736b670a1e )