File manager - Edit - /usr/local/cpanel/3rdparty/perl/542/cpanel-lib/Net/Curl/Promiser.pm
Back
package Net::Curl::Promiser; use strict; use warnings; our $VERSION = '0.20'; =encoding utf-8 =head1 NAME Net::Curl::Promiser - Asynchronous L<libcurl|https://curl.haxx.se/libcurl/>, the easy way! =head1 DESCRIPTION =begin html <a href='https://coveralls.io/github/FGasper/p5-Net-Curl-Promiser?branch=master'><img src='https://coveralls.io/repos/github/FGasper/p5-Net-Curl-Promiser/badge.svg?branch=master' alt='Coverage Status' /></a> =end html L<Net::Curl::Multi> is powerful but tricky to use: polling, callbacks, timers, etc. This module does all of that for you and puts a Promise interface on top of it, so asynchronous I/O becomes almost as simple as synchronous I/O. L<Net::Curl::Promiser> itself is a base class; you’ll need to use a subclass that works with your chosen event interface. This distribution provides the following usable subclasses: =over =item * L<Net::Curl::Promiser::Mojo> (for L<Mojolicious>) =item * L<Net::Curl::Promiser::AnyEvent> (for L<AnyEvent>) =item * L<Net::Curl::Promiser::IOAsync> (for L<IO::Async>) =item * L<Net::Curl::Promiser::Select> (for manually-written C<select()> loops) =back If the event interface you want to use isn’t compatible with one of the above, you’ll need to create your own L<Net::Curl::Promiser> subclass. This is undocumented but pretty simple; have a look at the ones above as well as another based on Linux’s L<epoll(7)> in the distribution’s F</examples>. =head1 MEMORY LEAK DETECTION This module will, by default, C<warn()> if its objects are C<DESTROY()>ed during Perl’s global destruction phase. To suppress this behavior, set C<$Net::Curl::Promiser::IGNORE_MEMORY_LEAKS> to a truthy value. =head1 PROMISE IMPLEMENTATION This class’s default Promise implementation is L<Promise::ES6>. You can use a different one by overriding the C<PROMISE_CLASS()> method in a subclass, as long as the substitute class’s C<new()> method works the same way as Promise::ES6’s (which itself follows the ECMAScript standard). (NB: L<Net::Curl::Promiser::Mojo> uses L<Mojo::Promise> instead of Promise::ES6.) =head2 B<Experimental> L<Promise::XS> support Try out experimental Promise::XS support by running with C<NET_CURL_PROMISER_PROMISE_ENGINE=Promise::XS> in your environment. This will override C<PROMISE_CLASS()>. =head1 DESIGN NOTES Internally each instance of this class uses an instance of L<Net::Curl::Multi> and an instance of L<Net::Curl::Promiser::Backend>. (The latter, in turn, is subclassed to provide logic specific to each event interface.) These are kept separate to avoid circular references. =cut #---------------------------------------------------------------------- use parent 'Net::Curl::Promiser::LeakDetector'; # So that Net::Curl::Easy::Code’s overloading gets set up: use Net::Curl::Easy (); use Net::Curl::Multi (); use constant _DEBUG => 0; use constant _DEFAULT_TIMEOUT => 1000; our $IGNORE_MEMORY_LEAKS; #---------------------------------------------------------------------- =head1 GENERAL-USE METHODS The following are of interest to any code that uses this module: =head2 I<CLASS>->new(@ARGS) Instantiates this class, including creation of an underlying L<Net::Curl::Multi> object. =cut sub new { my ($class, @args) = @_; my %props = ( callbacks => {}, to_fail => {}, ignore_leaks => $IGNORE_MEMORY_LEAKS, ); my $self = bless \%props, $class; my $multi = Net::Curl::Multi->new(); $self->{'multi'} = $multi; my $backend = $self->_INIT(\@args); $self->{'backend'} = $backend; $multi->setopt( Net::Curl::Multi::CURLMOPT_SOCKETDATA, $backend, ); $multi->setopt( Net::Curl::Multi::CURLMOPT_SOCKETFUNCTION, \&_socket_fn, ); return $self; } #---------------------------------------------------------------------- =head2 promise($EASY) = I<OBJ>->add_handle( $EASY ) A passthrough to the underlying L<Net::Curl::Multi> object’s method of the same name, but the return is given as a Promise object. That promise resolves with the passed-in $EASY object. It rejects with either the error given to C<fail_handle()> or the error that L<Net::Curl::Multi> object’s C<info_read()> returns. B<IMPORTANT:> As with libcurl itself, HTTP-level failures (e.g., 4xx and 5xx responses) are B<NOT> considered failures at this level. =cut sub add_handle { my ($self, $easy) = @_; return $self->{'backend'}->add_handle($easy, $self->{'multi'}); } =head2 $obj = I<OBJ>->cancel_handle( $EASY ) Prematurely cancels $EASY. The associated promise will be abandoned in pending state, never to resolve nor reject. Returns I<OBJ>. =cut sub cancel_handle { my ($self, $easy) = @_; $self->{'backend'}->cancel_handle($easy, $self->{'multi'}); return $self; } =head2 $obj = I<OBJ>->fail_handle( $EASY, $REASON ) Like C<cancel_handle()> but rejects $EASY’s associated promise with the given $REASON. Returns I<OBJ>. =cut sub fail_handle { my ($self, $easy, $reason) = @_; if (!defined $reason || !length $reason) { require Carp; Carp::carp("fail_handle(): no reason given"); } $self->{'backend'}->fail_handle($easy, $reason, $self->{'multi'}); return $self; } #---------------------------------------------------------------------- =head2 $obj = I<OBJ>->setopt( … ) A passthrough to the underlying L<Net::Curl::Multi> object’s method of the same name. Returns I<OBJ> to facilitate chaining. This class requires control of certain L<Net::Curl::Multi> options; if you attempt to set one of these here you’ll get an exception. =cut sub _SETOPT_FORBIDDEN { qw( SOCKETFUNCTION SOCKETDATA ) }; sub setopt { my $self = shift; for my $opt ( $self->_SETOPT_FORBIDDEN() ) { my $fullopt = "CURLMOPT_$opt"; if ($_[0] == Net::Curl::Multi->can($fullopt)->()) { my $ref = ref $self; die "Don’t set $fullopt via $ref!"; } } $self->{'multi'}->setopt(@_); return $self; } =head2 $obj = I<OBJ>->handles( … ) A passthrough to the underlying L<Net::Curl::Multi> object’s method of the same name. =cut sub handles { return shift()->{'multi'}->handles(); } #---------------------------------------------------------------------- sub _socket_fn { my ( $multi, $fd, $action, $backend ) = @_[0, 2, 3, 5]; # IMPORTANT: Removing handles within this function is likely to # corrupt libcurl. if ($action == Net::Curl::Multi::CURL_POLL_IN) { print STDERR "FD $fd, IN\n" if _DEBUG; $backend->SET_POLL_IN($fd, $multi); } elsif ($action == Net::Curl::Multi::CURL_POLL_OUT) { print STDERR "FD $fd, OUT\n" if _DEBUG; $backend->SET_POLL_OUT($fd, $multi); } elsif ($action == Net::Curl::Multi::CURL_POLL_INOUT) { print STDERR "FD $fd, INOUT\n" if _DEBUG; $backend->SET_POLL_INOUT($fd, $multi); } elsif ($action == Net::Curl::Multi::CURL_POLL_REMOVE) { print STDERR "FD $fd, STOP\n" if _DEBUG; $backend->STOP_POLL($fd, $multi); } else { warn( __PACKAGE__ . ": Unrecognized action $action on FD $fd\n" ); } return 0; } #---------------------------------------------------------------------- =head1 EXAMPLES See the distribution’s F</examples> directory. =head1 SEE ALSO Try L<Net::Curl::Easier> for a more polished variant of Net::Curl::Easy. L<Net::Curl::Simple> implements a similar idea to this module but doesn’t return promises. It has a more extensive interface that provides a more “perlish” experience than L<Net::Curl::Easy>. If you use L<AnyEvent>, then L<AnyEvent::XSPromises> with L<AnyEvent::YACurl> may be a nicer fit for you. =head1 REPOSITORY L<https://github.com/FGasper/p5-Net-Curl-Promiser> =head1 LICENSE & COPYRIGHT Copyright 2019-2020 Gasper Software Consulting. This library is licensed under the same terms as Perl itself. =cut 1;
| ver. 1.4 |
Github
|
.
| PHP 8.1.34 | Generation time: 0.03 |
proxy
|
phpinfo
|
Settings