File Coverage

lib/XML/Compile/RPC/Client.pm
Criterion Covered Total %
statement 58 84 69.0
branch 8 18 44.4
condition 3 10 30.0
subroutine 13 21 61.9
pod 6 7 85.7
total 88 140 62.8


line stmt bran cond sub pod time code
1             # Copyrights 2009-2020 by [Mark Overmeer ].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.02.
5             # This code is part of distribution XML-Compile-RPC. Meta-POD processed
6             # with OODoc into POD and HTML manual-pages. See README.md
7             # Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
8              
9             package XML::Compile::RPC::Client;
10 4     4   2245 use vars '$VERSION';
  4         23  
  4         248  
11             $VERSION = '0.20';
12              
13              
14 4     4   23 use warnings;
  4         8  
  4         87  
15 4     4   19 use strict;
  4         5  
  4         67  
16              
17 4     4   1147 use XML::Compile::RPC ();
  4         12  
  4         138  
18 4     4   1604 use XML::Compile::RPC::Util qw/fault_code/;
  4         8  
  4         292  
19              
20 4     4   25 use Log::Report 'xml-compile-rpc', syntax => 'LONG';
  4         7  
  4         24  
21 4     4   2590 use Time::HiRes qw/gettimeofday tv_interval/;
  4         5081  
  4         17  
22 4     4   2320 use HTTP::Request ();
  4         74757  
  4         99  
23 4     4   2371 use LWP::UserAgent ();
  4         81889  
  4         3465  
24              
25              
26 3     3 1 337 sub new(@) { my $class = shift; (bless {}, $class)->init({@_}) }
  3         20  
27              
28             sub init($)
29 3     3 0 11 { my ($self, $args) = @_;
30 3   33     34 $self->{user_agent} = $args->{user_agent} || LWP::UserAgent->new;
31 3   50     8054 $self->{xmlformat} = $args->{xmlformat} || 0;
32 3         9 $self->{auto_under} = $args->{autoload_underscore_is};
33             $self->{destination} = $args->{destination}
34 3 50       14 or report ERROR => __x"client requires a destination parameter";
35              
36             # convert header template into header object
37 3         8 my $headers = $args->{http_header};
38 3 50       14 $headers = HTTP::Headers->new(@{$headers || []})
  3 50       38  
39             unless UNIVERSAL::isa($headers, 'HTTP::Headers');
40              
41             # be sure we have a content-type
42 3 50       38 $headers->content_type
43             or $headers->content_type('text/xml');
44              
45 3         67 $self->{headers} = $headers;
46 3   33     63 $self->{schemas} = $args->{schemas} ||= XML::Compile::RPC->new;
47 3         13 $self;
48             }
49              
50             #--------------
51              
52              
53 0     0 1 0 sub headers() {shift->{headers}}
54 0     0 1 0 sub schemas() {shift->{schemas}}
55              
56             #--------------
57              
58             my $trace;
59 0     0 1 0 sub trace() {$trace}
60              
61              
62             sub printTrace(;$)
63 0     0 1 0 { my $self = shift;
64 0   0     0 my $fh = shift || \*STDERR;
65 0         0 my $trace = $self->trace;
66 0         0 $fh->print("response: ",$trace->{response}->status_line, "\n");
67 0         0 $fh->print("elapse: $trace->{total_elapse}\n");
68             }
69              
70              
71             sub call($@)
72 0     0 1 0 { my $self = shift;
73 0         0 my $start = [gettimeofday];
74              
75 0         0 my $request = $self->_request($self->_callmsg(@_));
76 0         0 my $format = [gettimeofday];
77              
78 0         0 my $response = $self->{user_agent}->request($request);
79 0         0 my $network = [gettimeofday];
80            
81 0         0 $trace =
82             { request => $request
83             , response => $response
84             , start_time => ($start->[0] + $start->[1]*10e-6)
85             , format_elapse => tv_interval($start, $format)
86             , network_elapse => tv_interval($format, $network)
87             };
88              
89 0 0       0 $response->is_success
90             or return ($response->code, $response->status_line, $trace);
91              
92 0         0 my ($rc, $decoded) = $self->_respmsg($response->decoded_content);
93 0         0 $trace->{decode_elapse} = tv_interval $network;
94 0         0 $trace->{total_elapse} = tv_interval $start;
95              
96 0         0 ($rc, $decoded, $trace);
97             }
98              
99             sub _callmsg($@)
100 4     4   3465 { my ($self, $method) = (shift, shift);
101              
102 4         8 my @params;
103 4         17 while(@_)
104 4         9 { my $type = shift;
105 4 50       43 my $value = UNIVERSAL::isa($type, 'HASH') ? $type : {$type => shift};
106 4         19 push @params, { value => $value };
107             }
108              
109 4         31 my $doc = XML::LibXML::Document->new('1.0', 'UTF-8');
110 4         51 my $xml = $self->{schemas}->writer('methodCall')->($doc
111             , { methodName => $method, params => { param => \@params }});
112 4         44663 $doc->setDocumentElement($xml);
113 4         59 $doc;
114             }
115              
116             sub _request($)
117 0     0   0 { my ($self, $doc) = @_;
118             HTTP::Request->new
119             ( POST => $self->{destination}
120             , $self->{headers}
121             , $doc->toString($self->{xmlformat})
122 0         0 );
123             }
124              
125             sub _respmsg($)
126 5     5   2973 { my ($self, $xml) = @_;
127 5 50       22 length $xml or return (1, "no xml received");
128              
129 5         46 my $data = $self->{schemas}->reader('methodResponse')->($xml);
130             return fault_code $data->{fault}
131 5 100       1643 if $data->{fault};
132              
133 4         10 my ($type, $value) = %{$data->{params}{param}{value}};
  4         22  
134 4         24 (0, $value);
135             }
136              
137             sub AUTOLOAD
138 0     0     { my $self = shift;
139 0           (my $proc = our $AUTOLOAD) =~ s/.*\:\://;
140             $proc =~ s/_/$self->{auto_under}/g
141 0 0         if defined $self->{auto_under};
142              
143 0           $self->call($proc, @_);
144             }
145              
146       0     sub DESTROY {} # avoid DESTROY to AUTOLOAD
147              
148             1;
149              
150             __END__