API-Docker
view release on metacpan or search on metacpan
lib/API/Docker/Error/Truncated.pm view on Meta::CPAN
API::Docker::Error::Truncated - The daemon closed before the response it announced was complete
=head1 VERSION
version 0.004
=head1 SYNOPSIS
# A tar the daemon stopped sending halfway is not a tar.
my $tar = eval { $docker->images->get_tar('busybox') };
if (my $err = $@) {
die $err unless ref $err
&& $err->isa('API::Docker::Error::Truncated');
warn 'got ' . length($err->partial) . ' of '
. $err->expected . ' bytes; retrying';
$tar = $docker->images->get_tar('busybox');
}
=head1 DESCRIPTION
L<API::Docker::Role::HTTP> croaks with an object of this class when the daemon
closed the connection in the middle of a response -- a status line with no
terminator, a header block with no blank line to close it, a body shorter than
its C<Content-Length>, a chunk shorter than its own header, a chunk header cut
in half, or a chunked body with no terminating zero chunk. It is raised in one
more place that is not a closed connection but has the same consequence: a
lib/API/Docker/Role/HTTP.pm view on Meta::CPAN
# socket, which is the same fill semantics this is here to get away from.
#
# A short positive read is never an end of stream and never an expiry. Over
# TLS it is the normal case, one plaintext record at a time; over a plain
# socket it is whatever the kernel had. Both are data.
#
# SSL_WANT_READ and SSL_WANT_WRITE are deliberately not retried. On a blocking
# socket they arrive as EWOULDBLOCK (IO::Socket::SSL's _skip_rw_error does
# `$! ||= EWOULDBLOCK`) and mean the underlying receive would have blocked --
# which, with SO_RCVTIMEO in force, is the bound firing and nothing else.
# Retrying would be a busy loop on WANT_READ and could not make progress on
# WANT_WRITE in any case, so they are reported as the timeout they are.
sub _pull {
my ($self, $sock, $ctx) = @_;
my $buf = $self->_read_buffer($sock);
while (1) {
# errno immediately before, errno immediately after, nothing in between:
# it is only meaningful after a failure, and any operation at all would
# overwrite it. See _timed_out.
lib/API/Docker/Role/HTTP.pm view on Meta::CPAN
=head2 Failure in the middle of a response
The daemon can also stop saying anything in the middle of saying it. A status
line with no terminator, a header block with no blank line to close it, a body
shorter than its C<Content-Length>, a chunk shorter than its own header, a
chunk header cut in half, a chunked body with no terminating zero chunk: each
of those is a response that ended before it was finished, and each croaks with
an L<API::Docker::Error::Truncated>.
my $tar = eval { $docker->images->get_tar('busybox') };
die $@ if $@ && !(ref $@
&& $@->isa('API::Docker::Error::Truncated'));
It is a structural check, so it needs no option, applies to every request, and
cannot fire on a response that is complete. Which question it asks depends on
how the piece is framed: where the response announced a length, what arrived
is compared against it; where the framing is by terminator instead -- the head
and the chunk headers -- it asks whether the terminator came before the stream
ended, which is decidable without anything to compare. The exception carries
what did arrive: C<< ->partial >> for a buffered request, C<< ->summary >> for
t/fixtures/images_list.json view on Meta::CPAN
],
"Names": [
"docker.io/library/alpine:3",
"docker.io/library/alpine:latest"
]
},
{
"Id": "sha256:c6348fa86ba0fb2108c9334f5fe913ddc6d853313e655891f133a0127c30099f",
"ParentId": "",
"RepoTags": [
"docker.io/library/busybox:latest"
],
"RepoDigests": [
"docker.io/library/busybox@sha256:1cfa4e2b09e127b9c4ed43578d3f3c18e7d44ea47b9ea98475c0cbe9086525f8",
"docker.io/library/busybox@sha256:dc2d74b28e4cf8984fa52af1f39bc7c3d9c73760b41a74d629f5d11b1ab28616"
],
"Created": 1778638909,
"Size": 4690894,
"SharedSize": -1,
"Labels": null,
"Containers": 0,
"Digest": "sha256:dc2d74b28e4cf8984fa52af1f39bc7c3d9c73760b41a74d629f5d11b1ab28616",
"History": [
"docker.io/library/busybox:latest"
],
"Names": [
"docker.io/library/busybox:latest"
]
},
{
"Id": "sha256:26b2eb03618e749084668eaff68cff8f81dda12d06ac641be7a6398b82a6f25b",
"ParentId": "",
"RepoTags": [
"docker.io/library/registry:2"
],
"RepoDigests": [
"docker.io/library/registry@sha256:46faa9a1ae6813194b53921a370f2f4f8c5e1aae228a89bceafef5847a6a3278",
( run in 1.310 second using v1.01-cache-2.11-cpan-54e63673c56 )