Net-Curl-Parallel
view release on metacpan or search on metacpan
lib/Net/Curl/Parallel.pm view on Meta::CPAN
# need to handle the 100 response
push @$headers, "Expect:"
unless grep{ $_ =~ /^Expect:/i } @$headers;
}
push @{$self->requests}, [$method, $uri, $headers, $content, $die];
return $idx;
}
sub setup_curl {
my ($self, $idx) = @_;
my ($method, $uri, $headers, $content, $die) = @{$self->requests->[$idx]};
# Both sides of the // can never be false because Net::Curl::Easy->new
# will always return true.
# uncoverable condition false
my $curl = shift(@{$self->avail_curl_pool}) // Net::Curl::Easy->new({});
# This is okay because the first parameter to Net::Curl::Easy->new() is the
# base object. We can put whatever we want into here.
$curl->{private} = {
response => Net::Curl::Parallel::Response->new,
idx => $idx,
uri => $uri,
die => $die,
};
# Basic config and tcp setup
$curl->setopt(CURLOPT_NOPROGRESS, 1);
$curl->setopt(CURLOPT_TCP_NODELAY, 1);
# Set connection timeout
$curl->setopt(CURLOPT_CONNECTTIMEOUT_MS, $self->connect_timeout)
if $self->connect_timeout;
# Keep idle TCP connections alive longer. Note - this option is available
# starting in libcurl 7.25.0
# uncoverable branch false
$curl->setopt(CURLOPT_TCP_KEEPALIVE, 1)
if &CURLOPT_TCP_KEEPALIVE;
# Set verbosity
$curl->setopt(CURLOPT_VERBOSE, 1)
if $self->verbose;
# HTTP
$curl->setopt(CURLOPT_ACCEPT_ENCODING, '');
$curl->setopt(CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
$curl->setopt(CURLOPT_USERAGENT, $self->agent);
$curl->setopt(CURLOPT_URL, $uri);
if ($method eq 'POST') {
$curl->setopt(CURLOPT_POST, 1);
$curl->setopt(CURLOPT_POSTFIELDS, $content);
}
# Configure headers
$curl->setopt(CURLOPT_HTTPHEADER, $headers)
if @$headers;
$curl->setopt(CURLOPT_WRITEDATA, $curl->{private}{response}->fh_body);
$curl->setopt(CURLOPT_WRITEHEADER, $curl->{private}{response}->fh_head);
# Configure redirect behavior
$curl->setopt(CURLOPT_FOLLOWLOCATION, $self->max_redirects > 0);
$curl->setopt(CURLOPT_MAXREDIRS, $self->max_redirects);
$curl->setopt(CURLOPT_AUTOREFERER, 1);
# Allow user override of ssl certificate verification
$curl->setopt(CURLOPT_SSL_VERIFYPEER, $self->verify_ssl_peer);
# Set request timeout
$curl->setopt(CURLOPT_TIMEOUT_MS, $self->request_timeout)
if $self->request_timeout;
# Clean up memory a little, but leave an undef at the index in the requests
# array since we are using the index as the key.
$self->requests->[$idx] = undef;
return $curl;
}
sub perform {
my $self = shift;
my $total = @{$self->requests};
my $pending = 0;
my $idx = 0;
$self->{responses} = []; # clear responses state from any prior runs
scope_guard{ $self->{requests} = [] }; # clear state for next run
until ($idx == $total && $pending == 0) {
# Fill empty slots
while ($idx < $total && $pending < $self->slots) {
$self->curl_multi->add_handle($self->setup_curl($idx));
++$pending;
++$idx;
}
$self->curl_multi->wait(1);
my $running = $self->curl_multi->perform;
# At least one request is complete
if ($running != $pending) {
my ($msg, $curl, $result) = $self->curl_multi->info_read;
# A request is complete
if ($msg) {
scope_guard{
--$pending;
$self->curl_multi->remove_handle($curl);
delete $curl->{private};
$curl->reset;
# Ignore max_curls while perform() is running
push @{$self->avail_curl_pool}, $curl;
};
my $ridx = $curl->{private}{idx};
( run in 1.406 second using v1.01-cache-2.11-cpan-39bf76dae61 )