File Coverage

lib/Neo4j/Driver/Net/HTTP/LWP.pm
Criterion Covered Total %
statement 73 73 100.0
branch 23 24 95.8
condition 22 22 100.0
subroutine 18 18 100.0
pod 10 10 100.0
total 146 147 99.3


line stmt bran cond sub pod time code
1 3     3   165236 use 5.010;
  3         12  
2 3     3   18 use strict;
  3         20  
  3         88  
3 3     3   14 use warnings;
  3         4  
  3         209  
4 3     3   1784 use utf8;
  3         902  
  3         18  
5              
6             package Neo4j::Driver::Net::HTTP::LWP;
7             # ABSTRACT: HTTP network adapter for libwww-perl
8             $Neo4j::Driver::Net::HTTP::LWP::VERSION = '1.02';
9              
10 3     3   2326 use Carp qw(croak);
  3         4  
  3         286  
11             our @CARP_NOT = qw(Neo4j::Driver::Net::HTTP);
12              
13 3     3   1526 use JSON::MaybeXS 1.003003 qw();
  3         44265  
  3         138  
14 3     3   4344 use LWP::UserAgent 6.04 qw();
  3         185373  
  3         128  
15 3     3   26 use URI 1.31;
  3         54  
  3         3223  
16              
17             my $CONTENT_TYPE = 'application/json';
18              
19              
20             sub new {
21 14     14 1 448233 my ($class, $driver) = @_;
22            
23 14         90 my $self = bless {
24             json_coder => JSON::MaybeXS->new(utf8 => 1, allow_nonref => 0),
25             }, $class;
26            
27 14         348 my $uri = $driver->config('uri');
28 14 100       175 if (my $auth = $driver->config('auth')) {
29 6 100       74 croak "Only HTTP Basic Authentication is supported" if $auth->{scheme} ne 'basic';
30 5   100     18 my $userid = $auth->{principal} // '';
31 5   100     22 my $passwd = $auth->{credentials} // '';
32             my $userinfo = join ':', map {
33 5         11 utf8::encode $_; # uri_escape doesn't handle wide characters
  10         165  
34 10         44 URI::Escape::uri_escape $_;
35             } $userid, $passwd;
36 5         117 $uri = $uri->clone;
37 5         83 $uri->userinfo($userinfo);
38             }
39 13         855 $self->{uri_base} = $uri;
40            
41 13         23 my $version = $Neo4j::Driver::Net::HTTP::LWP::VERSION;
42 13 100       89 my $agent = $self->{agent} = LWP::UserAgent->new(
43             # User-Agent: Neo4j-Driver/0.21 libwww-perl/6.52
44             agent => sprintf("Neo4j-Driver%s ", $version ? "/$version" : ""),
45             timeout => $driver->config('timeout'),
46             );
47 13         9153 $agent->default_headers->header( 'X-Stream' => 'true' );
48            
49 13 100       690 if ($uri->scheme eq 'https') {
50 4   100     142 my $unencrypted = defined $driver->config('encrypted') && ! $driver->config('encrypted');
51 4 100       51 croak "HTTPS does not support unencrypted communication; use HTTP" if $unencrypted;
52 3         9 $agent->ssl_opts( verify_hostname => 1 );
53 3 100       50 if (defined( my $trust_ca = $driver->config('trust_ca') )) {
54 1 50       134 croak sprintf "trust_ca file '%s' can't be used: %s", $trust_ca, $!
55             unless open my $fh, '<', $trust_ca;
56 1         5 $agent->ssl_opts( SSL_ca_file => $trust_ca );
57             }
58             }
59             else {
60 9 100       185 croak "HTTP does not support encrypted communication; use HTTPS" if $driver->config('encrypted');
61             }
62            
63 11         288 return $self;
64             }
65              
66              
67 5     5 1 5794 sub ua { shift->{agent} }
68              
69 8     8 1 4782 sub uri { shift->{uri_base} }
70              
71 2     2 1 1743 sub json_coder { shift->{json_coder} }
72              
73 4   100 4 1 1586 sub http_reason { shift->{response}->message // '' }
74              
75 2   100 2 1 1323 sub date_header { scalar shift->{response}->header('Date') // '' }
76              
77              
78             sub http_header {
79 12     12 1 8153 my $response = shift->{response};
80 12   100     34 my $header = {
      100        
      100        
81             content_type => scalar $response->header('Content-Type') // '',
82             location => scalar $response->header('Location') // '',
83             status => $response->code // '',
84             success => $response->is_success,
85             };
86 12 100 100     1007 if ( ! $header->{success} && $response->header('Client-Warning') // '' eq 'Internal response' ) {
      100        
87 2         55 $header->{content_type} = '';
88 2         3 $header->{status} = '';
89             }
90 12         225 return $header;
91             }
92              
93              
94             sub fetch_event {
95 3     3 1 4141 my ($self) = @_;
96 3 100       9 $self->{buffer} = [grep { length } split m/\n|\x{1e}/, $self->fetch_all] unless defined $self->{buffer};
  3         41  
97 3         4 return shift @{$self->{buffer}};
  3         12  
98             }
99              
100              
101             sub fetch_all {
102 4     4 1 10552 my ($self) = @_;
103 4         11 return $self->{response}->content;
104             }
105              
106              
107             sub request {
108 5     5 1 23049 my ($self, $method, $url, $json, $accept, $mode) = @_;
109            
110 5         10 $self->{buffer} = undef;
111            
112 5         33 $url = URI->new_abs( $url, $self->{uri_base} );
113 5         1210 $method = lc $method;
114 5 100       10 if ($json) {
115             $self->{response} = $self->{agent}->$method(
116             $url,
117             'Accept' => $accept,
118 3 100       32 'Content' => $self->{json_coder}->encode($json),
119             'Content-Type' => $CONTENT_TYPE,
120             $mode ? ('Access-Mode' => $mode) : ()
121             );
122             }
123             else {
124 2         12 $self->{response} = $self->{agent}->$method(
125             $url,
126             'Accept' => $accept,
127             );
128             }
129             }
130              
131              
132             1;
133              
134             __END__