1 package Net::HTTPS::Any;
5 use base qw( Exporter );
6 use vars qw(@EXPORT_OK $ssl_module $skip_NetSSLeay);
10 @EXPORT_OK = qw( https_get https_post );
17 die if defined($skip_NetSSLeay) && $skip_NetSSLeay;
19 Net::SSLeay->VERSION(1.30);
22 # qw(get_https post_https make_form make_headers);
23 $ssl_module = 'Net::SSLeay';
28 require LWP::UserAgent;
29 require HTTP::Request::Common;
30 require Crypt::SSLeay;
32 #import HTTP::Request::Common qw(GET POST);
33 $ssl_module = 'Crypt::SSLeay';
37 unless ($ssl_module) {
38 die "One of Net::SSLeay (v1.30 or later)"
39 . " or Crypt::SSLeay (+LWP) is required";
46 Net::HTTPS::Any - Simple HTTPS client using whichever underlying SSL module is available
50 our $VERSION = '0.11_01';
54 use Net::HTTPS::Any qw(https_get https_post);
56 ( $page, $response, %reply_headers )
58 { 'host' => 'www.fortify.net',
60 'path' => '/sslcheck.html',
61 'args' => { 'field' => 'value' },
62 #'args' => [ 'field'=>'value' ], #order preserved
66 ( $page, $response, %reply_headers )
68 'host' => 'www.google.com',
70 'path' => '/accounts/ServiceLoginAuth',
71 'args' => { 'field' => 'value' },
72 #'args' => [ 'field'=>'value' ], #order preserved
79 This is a simple wrapper around either of the two available SSL
80 modules. It offers a unified API for sending GET and POST requests over HTTPS
81 and receiving responses.
83 It depends on Net::SSLeay _or_ ( Crypt::SSLeay and LWP::UserAgent ).
85 =head1 WHY THIS MODULE
87 If you just want to write something that speaks HTTPS, you don't need this
88 module. Just go ahead and use whichever of the two modules is good for you.
91 On the other hand, if you are a CPAN author or distribute a Perl application,
92 especially if you aim to support multiple OSes/disributions, using this module
93 for speaking HTTPS may make things easier on your users. It allows your code
94 to be used with either SSL implementation.
98 =head2 https_get HASHREF | FIELD => VALUE, ...
100 Accepts parameters as either a hashref or a list of fields and values.
112 =item headers (hashref)
114 For example: { 'X-Header1' => 'value', ... }
120 # Defaults to "application/x-www-form-urlencoded" if not specified.
124 CGI arguments, either as a hashref or a listref. In the latter case, ordering
125 is preserved (see L<Tie::IxHash> to do so when passing a hashref).
129 Set true to enable debugging.
133 Returns a list consisting of the page content as a string, the HTTP
134 response code and message (i.e. "200 OK" or "404 Not Found"), and a list of
135 key/value pairs representing the HTTP response headers.
140 my $opts = ref($_[0]) ? shift : { @_ }; #hashref or list
142 # accept a hashref or a list (keep it ordered)
143 my $post_data = {}; # technically get_data, pedant
144 if ( exists($opts->{'args'}) && ref($opts->{'args'}) eq 'HASH' ) {
145 $post_data = $opts->{'args'};
146 } elsif ( exists($opts->{'args'}) && ref($opts->{'args'}) eq 'ARRAY' ) {
147 tie my %hash, 'Tie::IxHash', @{ $opts->{'args'} };
151 $opts->{'port'} ||= 443;
152 #$opts->{"Content-Type"} ||= "application/x-www-form-urlencoded";
156 if ( ref( $opts->{headers} ) eq "HASH" ) {
157 %headers = %{ $opts->{headers} };
159 $headers{'Host'} ||= $opts->{'host'};
161 my $path = $opts->{'path'};
162 if ( keys %$post_data ) {
165 map { uri_escape($_) . '=' . uri_escape( $post_data->{$_} ) }
169 if ( $ssl_module eq 'Net::SSLeay' ) {
171 no warnings 'uninitialized';
173 import Net::SSLeay qw(get_https make_headers);
174 my $headers = make_headers(%headers);
176 $Net::SSLeay::trace = $opts->{'debug'}
177 if exists $opts->{'debug'} && $opts->{'debug'};
179 my( $res_page, $res_code, @res_headers ) =
180 get_https( $opts->{'host'},
185 #$opts->{"Content-Type"},
188 $res_code =~ /^(HTTP\S+ )?(.*)/ and $res_code = $2;
190 return ( $res_page, $res_code, @res_headers );
192 } elsif ( $ssl_module eq 'Crypt::SSLeay' ) {
194 import HTTP::Request::Common qw(GET);
196 my $url = 'https://' . $opts->{'host'};
197 $url .= ':' . $opts->{'port'}
198 unless $opts->{'port'} == 443;
201 my $ua = new LWP::UserAgent;
202 foreach my $hdr ( keys %headers ) {
203 $ua->default_header( $hdr => $headers{$hdr} );
205 $ENV{HTTPS_DEBUG} = $opts->{'debug'} if exists $opts->{'debug'};
206 my $res = $ua->request( GET($url) );
208 my @res_headers = map { $_ => $res->header($_) }
209 $res->header_field_names;
211 return ( $res->content, $res->code. ' '. $res->message, @res_headers );
214 die "unknown SSL module $ssl_module";
219 =head2 https_post HASHREF | FIELD => VALUE, ...
221 Accepts parameters as either a hashref or a list of fields and values.
233 =item headers (hashref)
235 For example: { 'X-Header1' => 'value', ... }
239 Defaults to "application/x-www-form-urlencoded" if not specified.
243 CGI arguments, either as a hashref or a listref. In the latter case, ordering
244 is preserved (see L<Tie::IxHash> to do so when passing a hashref).
248 Raw content (overrides args). A simple scalar containing the raw content.
252 Set true to enable debugging in the underlying SSL module.
256 Returns a list consisting of the page content as a string, the HTTP
257 response code and message (i.e. "200 OK" or "404 Not Found"), and a list of
258 key/value pairs representing the HTTP response headers.
263 my $opts = ref($_[0]) ? shift : { @_ }; #hashref or list
265 # accept a hashref or a list (keep it ordered). or a scalar of content.
267 if ( exists($opts->{'args'}) && ref($opts->{'args'}) eq 'HASH' ) {
268 $post_data = $opts->{'args'};
269 } elsif ( exists($opts->{'args'}) && ref($opts->{'args'}) eq 'ARRAY' ) {
270 tie my %hash, 'Tie::IxHash', @{ $opts->{'args'} };
273 if ( exists $opts->{'content'} ) {
274 $post_data = $opts->{'content'};
277 $opts->{'port'} ||= 443;
278 $opts->{"Content-Type"} ||= "application/x-www-form-urlencoded";
282 if ( ref( $opts->{headers} ) eq "HASH" ) {
283 %headers = %{ $opts->{headers} };
285 $headers{'Host'} ||= $opts->{'host'};
287 if ( $ssl_module eq 'Net::SSLeay' ) {
289 no warnings 'uninitialized';
291 import Net::SSLeay qw(post_https make_headers make_form);
292 my $headers = make_headers(%headers);
294 $Net::SSLeay::trace = $opts->{'debug'}
295 if exists $opts->{'debug'} && $opts->{'debug'};
297 my $raw_data = ref($post_data) ? make_form(%$post_data) : $post_data;
299 $Net::SSLeay::trace = $opts->{'debug'}
300 if exists $opts->{'debug'} && $opts->{'debug'};
302 my( $res_page, $res_code, @res_headers ) =
303 post_https( $opts->{'host'},
308 $opts->{"Content-Type"},
311 $res_code =~ /^(HTTP\S+ )?(.*)/ and $res_code = $2;
313 return ( $res_page, $res_code, @res_headers );
315 } elsif ( $ssl_module eq 'Crypt::SSLeay' ) {
317 import HTTP::Request::Common qw(POST);
319 my $url = 'https://' . $opts->{'host'};
320 $url .= ':' . $opts->{'port'}
321 unless $opts->{'port'} == 443;
322 $url .= $opts->{'path'};
324 my $ua = new LWP::UserAgent;
325 foreach my $hdr ( keys %headers ) {
326 $ua->default_header( $hdr => $headers{$hdr} );
329 $ENV{HTTPS_DEBUG} = $opts->{'debug'} if exists $opts->{'debug'};
332 if ( ref($post_data) ) {
333 $res = $ua->request( POST( $url, [%$post_data] ) );
336 my $req = new HTTP::Request( 'POST' => $url );
337 $req->content_type( $opts->{"Content-Type"} );
338 $req->content($post_data);
339 $res = $ua->request($req);
342 my @res_headers = map { $_ => $res->header($_) }
343 $res->header_field_names;
345 return ( $res->content, $res->code. ' '. $res->message, @res_headers );
348 die "unknown SSL module $ssl_module";
355 Ivan Kohler, C<< <ivan-net-https-any at freeside.biz> >>
359 Please report any bugs or feature requests to C<bug-net-https-any at rt.cpan.org>, or through
360 the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-HTTPS-Any>. I will be notified, and then you'll
361 automatically be notified of progress on your bug as I make changes.
365 You can find documentation for this module with the perldoc command.
367 perldoc Net::HTTPS::Any
369 You can also look for information at:
373 =item * RT: CPAN's request tracker
375 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-HTTPS-Any>
377 =item * AnnoCPAN: Annotated CPAN documentation
379 L<http://annocpan.org/dist/Net-HTTPS-Any>
383 L<http://cpanratings.perl.org/d/Net-HTTPS-Any>
387 L<http://search.cpan.org/dist/Net-HTTPS-Any>
391 =head1 COPYRIGHT & LICENSE
393 Copyright 2008-2010 Freeside Internet Services, Inc. (http://freeside.biz/)
396 This program is free software; you can redistribute it and/or modify it
397 under the same terms as Perl itself.