File Coverage

blib/lib/AnyEvent/HTTP/MXHR.pm
Criterion Covered Total %
statement 53 66 80.3
branch 8 16 50.0
condition 2 4 50.0
subroutine 9 11 81.8
pod 1 1 100.0
total 73 98 74.4


line stmt bran cond sub pod time code
1             package AnyEvent::HTTP::MXHR;
2 2     2   932142 use strict;
  2         8  
  2         148  
3 2     2   12 use AnyEvent '6.01';
  2         8  
  2         50  
4 2     2   4038 use AnyEvent::HTTP;
  2         38310  
  2         212  
5 2     2   28 use AnyEvent::Util qw(guard);
  2         6  
  2         100  
6 2     2   10 use base qw(Exporter);
  2         4  
  2         2246  
7             our @EXPORT = qw(mxhr_get);
8             our $VERSION = '0.00007';
9              
10             sub mxhr_get ($@) {
11 1     1 1 50995 my $cb = pop;
12 1         14 my ($uri, %args) = @_;
13              
14             my $on_error = delete $args{on_error} || sub {
15 0     0     require Carp;
16 0           Carp::confess("@_");
17 1   50     9 };
18 1   50 0   6 my $on_eof = delete $args{on_eof} || sub { };
  0            
19 1         3 my %state;
20             $state{guard} = http_get $uri, %args,
21             want_body_handle => 1,
22             on_error => $on_error,
23             on_header => sub {
24 1     1   15781 my ($headers) = @_;
25              
26 1 50       18 if ($headers->{"content-type"} =~ m{^multipart/mixed\s*;\s*boundary="([^"]+)"}) {
27 1         5 $state{boundary} = $1;
28 1         106 $state{boundary_re} = qr!(?:^|\r?\n)--$state{boundary}\n?!;
29 1         7 return 1;
30             } else {
31 0         0 %state = ();
32 0         0 $on_error->("Header not found");
33 0         0 return ();
34             }
35             },
36             sub {
37 1     1   214 my $handle = shift;
38 1 50       6 if (! $handle) {
39 0         0 undef $state{guard};
40 0         0 %state = ();
41 0 0       0 $on_error->("Connection failed") if $on_error;
42 0         0 return ();
43             }
44              
45 1         3 $state{handle} = $handle;
46              
47 1         2 my $callback; $callback = sub {
48 11         6767905 my ($handle, $data) = @_;
49              
50 11 50       66 return unless %state;
51 11         60 $data =~ s/^\s+//;
52 11 50       201 if ($data !~ s/(?:^|\r?\n)--$state{boundary}\n?$// ) {
53             # shouldn't even get here
54 0 0       0 if ($handle->{on_error}) {
55 0         0 $handle->{on_error}->("No boundary found");
56             }
57 0         0 return;
58             }
59              
60 11 100       226 if ($data !~ s/^(.+?)\015?\012\015?\012// ) {
61             # XXX opting to ignore the data, but should we?
62 1         7 $handle->push_read(regex => $state{boundary_re}, $callback);
63 1         21 return 1;
64             }
65 10         50 my $headers = $1;
66              
67 10         109 my %headers = map {
68 10         70 my ($n, $v) = split(/:\s*/, $_, 2);
69             # lower case it to align with the rest of AE::HTTP
70 10         45 $n = lc $n;
71 10         82 ($n, $v);
72             } split(/\r?\n/, $headers);
73 10 100       37 if (! eval { $cb->($data, \%headers, $handle) }) {
  10         51  
74 1         38 %state = ();
75 1         5 return;
76             }
77              
78 9         3213844 $handle->push_read(regex => $state{boundary_re}, $callback);
79 9         405 return 1;
80 1         25 };
81            
82 1         8 $handle->push_read(regex => $state{boundary_re}, $callback );
83 1         70 return 1;
84             }
85 1         99 ;
86              
87 1     1   4128 return guard { %state = () };
  1         683908  
88              
89             }
90              
91             1;
92              
93             __END__