5

It is necessary to read only part of the page (n bytes) and close the connection, how to do this on AnyEvent::HTTP ?

Dmitriy
  • 463
  • 1
  • 5
  • 12
  • 2
    It looks like ikegami's answer is almost certainly what you're looking for, but it's worth pointing out that the 'Range' feature is built in to the HTTP protocol for exactly this type of request. If the server you are talking to supports it, you can add a header to your request like this: `Range: bytes=0-4096` to get the first 4KB. – Grant McLean Apr 11 '17 at 21:19
  • @GrantMcLean, Thank you, useful information! – Dmitriy Apr 12 '17 at 13:34

1 Answers1

6

on_body is called repeatedly as chunks arrive. Returning false from on_body terminates the download.

sub my_http_request {
   my $cb = pop;
   my ($method, $url, %args) = @_;

   croak("Unsupported: on_body")          if $args{on_body};
   croak("Unsupported: want_body_handle") if $args{want_body_handle};

   my $max_to_read = delete($args{max_to_read});

   my $data;
   return http_request(
      $method => $url,
      %args,
      on_body => sub {
         #my ($chunk, $headers) = @_;
         $data .= $_[0];
         return !defined($max_to_read) || length($data) < $max_to_read;
      },
      sub {
         my (undef, $headers) = @_;
         $cb->($data, $headers);
      },
   );
}

Use my_http_request just like http_request, except it accepts an optional max_to_read parameter.

For example,

my $cb = AnyEvent->condvar();
my_http_request(
   GET => 'http://...',
   ...
   max_to_read => ...,
   $cb,
);

my ($data, $headers) = $cb->recv();

For example,

my $done = AnyEvent->condvar();
my_http_request(
   GET => 'http://...',
   ...
   max_to_read => ...,
   sub {
      my ($data, $headers) = @_;
      ...
      $done->send();
   },
);

$done->recv();
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • I meant to make `max_to_read` optional. Fixed. Also removed comment for code that was removed, and made parameter order consistent with the original function. – ikegami Apr 12 '17 at 15:37