File Coverage

blib/lib/Business/MaxMind/HTTPBase.pm
Criterion Covered Total %
statement 27 80 33.7
branch 3 26 11.5
condition n/a
subroutine 6 14 42.8
pod 4 8 50.0
total 40 128 31.2


line stmt bran cond sub pod time code
1             package Business::MaxMind::HTTPBase;
2              
3 1     1   18 use 5.006;
  1         2  
  1         34  
4              
5 1     1   3 use strict;
  1         1  
  1         22  
6              
7 1     1   445 use LWP::Protocol::https;
  1         123750  
  1         38  
8 1     1   8 use LWP::UserAgent;
  1         1  
  1         16  
9 1     1   4 use URI::Escape;
  1         1  
  1         733  
10              
11             our $VERSION = '1.57';
12              
13             my $API_VERSION = join( '/', 'Perl', $VERSION );
14              
15             # default minfraud servers
16             my @defaultservers = (
17             'minfraud.maxmind.com', 'minfraud-us-east.maxmind.com',
18             'minfraud-us-west.maxmind.com'
19             );
20              
21             sub new {
22 2     2 1 798 my $i = 0;
23 2         5 my ($class) = shift;
24 2 50       6 if ( $class eq 'Business::MaxMind::HTTPBase' ) {
25 0         0 die
26             "Business::MaxMind::HTTPBase is an abstract class - use a subclass instead";
27             }
28 2         5 my $self = {@_};
29 2         6 bless $self, $class;
30 2 100       12 $self->{isSecure} = 1 unless exists $self->{isSecure};
31 2         5 for my $server (@defaultservers) {
32 6         10 $self->{servers}->[$i] = $server;
33 6         8 $i++;
34             }
35 2         16 $self->{ua} = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 } );
36 2         3643 $self->_init;
37 2         9 return $self;
38             }
39              
40             sub getServers {
41 0 0   0 0   return [ @{ $_[0]->{servers} || [] } ];
  0            
42             }
43              
44             sub setServers {
45 0     0 0   my ( $self, $serverarrayref ) = @_;
46 0           $self->{servers} = [@$serverarrayref];
47             }
48              
49             sub query {
50 0     0 1   my ($self) = @_;
51 0           my $s = $self->{servers};
52 0           my $datetime;
53              
54 0           for my $server (@$s) {
55 0           my $result = $self->querySingleServer($server);
56 0 0         return $result if $result;
57             }
58 0           return 0;
59             }
60              
61             sub input {
62 0     0 1   my $self = shift;
63 0           my %vars = @_;
64 0           while ( my ( $k, $v ) = each %vars ) {
65 0 0         unless ( exists $self->{allowed_fields}->{$k} ) {
66 0           die "invalid input $k - perhaps misspelled field?";
67             }
68 0           $self->{queries}->{$k} = $self->filter_field( $k, $v );
69             }
70             }
71              
72             # sub-class should override this if it needs to filter inputs
73             sub filter_field {
74 0     0 0   my ( $self, $name, $value ) = @_;
75 0           return $value;
76             }
77              
78             sub output {
79 0     0 1   my $self = shift;
80 0           return $self->{output};
81             }
82              
83             # if possible send the escaped string as latin1 for backward compatibility.
84             # That makes a difference for chars 128..255
85             # otherwise use utf8 encoding.
86             #
87             sub _mm_uri_escape {
88 0 0   0     return uri_escape( $_[0] ) if $] < 5.007;
89 0 0         return utf8::downgrade( my $t = $_[0], 1 )
90             ? uri_escape( $_[0] )
91             : uri_escape_utf8( $_[0] );
92             }
93              
94             sub querySingleServer {
95 0     0 0   my ( $self, $server ) = @_;
96 0 0         my $url
97             = ( $self->{isSecure} ? 'https' : 'http' ) . '://'
98             . $server . '/'
99             . $self->{url};
100 0           my $check_field = $self->{check_field};
101 0           my $queries = $self->{queries};
102 0           my $query_string = join(
103             '&',
104 0           map { "$_=" . _mm_uri_escape( $queries->{$_} ) } keys %$queries
105             );
106 0           $query_string .= "&clientAPI=$API_VERSION";
107 0 0         if ( $self->{"timeout"} > 0 ) {
108 0           $self->{ua}->timeout( $self->{"timeout"} );
109             }
110 0           my $request = HTTP::Request->new( 'POST', $url );
111 0           $request->content_type('application/x-www-form-urlencoded');
112 0           $request->content($query_string);
113 0 0         if ( $self->{debug} ) {
114 0           print STDERR "sending HTTP::Request: " . $request->as_string;
115             }
116 0           my $response = $self->{ua}->request($request);
117 0 0         if ( $response->is_success ) {
118 0           my $content = $response->content;
119 0           my @kvpair = split( ';', $content );
120 0           my %output;
121 0           for my $kvp (@kvpair) {
122 0           my ( $key, $value ) = split( '=', $kvp, 2 );
123 0           $output{$key} = $value;
124             }
125 0 0         unless ( exists $output{$check_field} ) {
126 0           return 0;
127             }
128 0           $self->{output} = \%output;
129 0           return 1;
130             }
131             else {
132 0 0         if ( $self->{debug} ) {
133 0           print STDERR "Error querying $server code: " . $response->code;
134             }
135 0           return 0;
136             }
137             }
138              
139             1;
140              
141             =pod
142              
143             =head1 NAME
144              
145             Business::MaxMind::HTTPBase - Base class for accessing HTTP web services
146              
147             =head1 VERSION
148              
149             version 1.57
150              
151             =head1 DESCRIPTION
152              
153             This is an abstract base class for accessing MaxMind web services.
154             Currently there are three subclasses, for Credit Card Fraud Detection,
155             Telephone Verification and Location Verification. This class can be
156             used for other HTTP based web services as well.
157              
158             =head1 METHODS
159              
160             =over 4
161              
162             =item new
163              
164             Class method that returns a new object that is a subclass of Business::MaxMind::HTTPBase.
165             Will die if you attempt to call this for the Business::MaxMind::HTTPBase class, instead
166             you should call it on one of its subclasses.
167              
168             =item input
169              
170             Sets input fields. See subclass for details on fields that should be set.
171             Returns 1 on success, 0 on failure.
172              
173             =item query
174              
175             Sends out query to MaxMind server and waits for response. If the primary
176             server fails to respond, it sends out a request to the secondary server.
177             Returns 1 on success, 0 on failure.
178              
179             =item output
180              
181             Returns the output returned by the MaxMind server as a hash reference.
182              
183             =back
184              
185             =head1 SEE ALSO
186              
187             L
188              
189             L
190              
191             =head1 AUTHORS
192              
193             =over 4
194              
195             =item *
196              
197             TJ Mather
198              
199             =item *
200              
201             Frank Mather
202              
203             =back
204              
205             =head1 COPYRIGHT AND LICENSE
206              
207             This software is Copyright (c) 2015 by MaxMind, Inc..
208              
209             This is free software, licensed under:
210              
211             The GNU General Public License, Version 2, June 1991
212              
213             =cut
214              
215             __END__