HTTP-LoadGen
view release on metacpan or search on metacpan
lib/HTTP/LoadGen.pm view on Meta::CPAN
}
sub delay {
my ($prefix, $param)=@_;
return if delete $param->{'skip'.$prefix.'delay'};
return unless exists $param->{$prefix.'delay'};
my $sec=$param->{$prefix.'delay'};
if( exists $param->{$prefix.'jitter'} ) {
my $jitter=$param->{$prefix.'jitter'};
$sec+=-$jitter+rnd(2*$jitter);
}
#D warn "\u${prefix}Delay: $sec sec\n";
Coro::Timer::sleep $sec if $sec>0;
}
my (%services, %known_iterators);
sub register_iterator {
my $code=pop;
if( Scalar::Util::reftype $code eq 'CODE' ) {
@known_iterators{@_}=($code)x(+@_);
} else {
die "CODE reference expected";
}
}
sub get_iterator {
my ($name)=@_;
exists $known_iterators{$name} and return $known_iterators{$name};
return $known_iterators{''};
}
{
my %keep=('user-agent'=>1, 'referer'=>1);
sub follow_3XX {
my ($rc, $el)=@_;
# we are stricter here than most browsers because we do not follow
# partial URLs.
if( $rc->[RC_STATUS]=~/^3/ and
exists $rc->[RC_HEADERS]->{location} and
$rc->[RC_HEADERS]->{location}->[0]=~m!^(https?):// # scheme
([^:/]+) # host
(:[0-9]+)? # optional port
(.*)!ix ) { # uri
# follow location
my $scheme=lc($1);
my $host=$2;
my $port=$3||$services{$scheme};
my $uri=$4||'/';
my @h;
if( exists $el->[RQ_PARAM]->{headers} ) {
my $hdr=$el->[RQ_PARAM]->{headers};
for (my $i=0; $i<@$hdr; $i+=2) {
push @h, $hdr->[$i], $hdr->[$i+1] if exists $keep{lc $hdr->[$i]};
}
}
return ['GET', $scheme, $host, $port, $uri,
{keepalive=>KEEPALIVE, followed=>1, headers=>\@h}];
}
}
}
BEGIN {
%services=(http=>80, https=>443);
register_iterator '', default=>sub {
my $urls=options->{URLList};
my $nurls=@$urls;
my $i=0;
return sub {
return if $i>=$nurls;
return $urls->[$i++];
};
};
register_iterator random_start=>sub {
my $urls=options->{URLList};
my $nurls=@$urls;
my ($i, $off)=(0, int rnd $nurls);
return sub {
return if $i>=$nurls;
return $urls->[($off+$i++) % $nurls];
};
};
register_iterator follow=>sub {
my %save_delay;
my $it=@_ ? $_[0] : get_iterator('')->();
return sub {
my ($rc, $el)=@_;
my $next=follow_3XX $rc, $el;
return $next if $next;
delay 'post', \%save_delay;
# get next request
$next=$it->($rc, $el);
return unless $next;;
# save postdelay
if( exists $next->[RQ_PARAM]->{postdelay} ) {
$save_delay{postdelay}=$next->[RQ_PARAM]->{postdelay};
$save_delay{postjitter}=$next->[RQ_PARAM]->{postjitter}
if exists $next->[RQ_PARAM]->{postjitter};
$next->[RQ_PARAM]->{skippostdelay}=1;
}
return $next;
};
};
register_iterator random_start_follow=>sub {
@_=get_iterator('random_start')->();
goto &{get_iterator 'follow'};
};
}
( run in 2.037 seconds using v1.01-cache-2.11-cpan-71847e10f99 )