This queue is for tickets about the SOAP-Lite CPAN distribution.

Report information
The Basics
Id:
104469
Status:
new
Priority:
Low/Low
Queue:

People
Owner:
Nobody in particular
Requestors:
john [...] calva.com
Cc:
AdminCc:

BugTracker
Severity:
(no value)
Broken in:
(no value)
Fixed in:
(no value)



Subject: PATCH_HTTP_KEEPALIVE breaks connection caching.
Date: Sat, 16 May 2015 13:04:16 +0200
To: bug-SOAP-Lite@rt.cpan.org
From: John Hughes <john@calva.com>
I wrote a little client using SOAP::Lite and was supprised to see that it was making a new https call for every SOAP call.

Investigation showed the problem was because PATCH_HTTP_KEEPALIVE was set.

in SOAP::Transport::HTTP The "patch" is:

*collect = sub {
            if ( defined $_[2]->header('Connection')
                && $_[2]->header('Connection') eq 'Keep-Alive' ) {
                my $data = $_[3]->();
                my $next =
                  $_[2]->header('Content-Length') &&
                    SOAP::Utils::bytelength($$data) ==
                        $_[2]->header('Content-Length')
                  ? sub { my $str = ''; \$str; }
                  : $_[3];
                my $done = 0;
                $_[3] = sub {
                    $done++ ? &$next : $data;
                };
            }
            goto &$collect;
        };

It calls the "collector" subroutine ($_[3]) once to get the response data if the "Connection: Keep-Alive" header is present.

But the collector subroutine in LWP::Protocol::http is:

sub {
        my $buf = ""; #prevent use of uninitialized value in SSLeay.xs
        my $n;
      READ:
        {
            $n = $socket->read_entity_body($buf, $size);
            unless (defined $n) {
                redo READ if $!{EINTR} || $!{EAGAIN} || $!{ENOTTY};
                die "read failed: $!";
            }
            redo READ if $n == -1;
        }
        $complete++ if !$n;
        return \$buf;
    }
The "$complete" flag is only set when $socket->read_entity_body returns 0, which never happens if the SOAP::Lite patch is in place.

Since LWP::Protocol::http thinks the reply isn't complete it doesn't cache the connection:

    # keep-alive support
    unless ($drop_connection) {
        if ($cache_key) {
            my %connection = map { (lc($_) => 1) }
                             split(/\s*,\s*/, ($response->header("Connection") || ""));
            if (($peer_http_version eq "1.1" && !$connection{close}) ||
                $connection{"keep-alive"})
            {
                $conn_cache->deposit($self->socket_type, $cache_key, $socket);
            }
        }
    }

So, unintuitively, if the server returns "Connection: Keep-Alive" the connection is not cached.

--
John Hughes, CalvaEDI S.A.S.
 


This service runs on Request Tracker, is sponsored by The Perl Foundation, and maintained by Best Practical Solutions.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.