libwww-perl / LWP-Protocol-https

Provide https support for LWP::UserAgent
https://metacpan.org/pod/LWP::Protocol::https
Other
16 stars 35 forks source link

Inherit with 'use parent' instead of 'use base' #78

Closed mtsanovv closed 6 months ago

mtsanovv commented 7 months ago

With #30, the way LWP::Protocol::https and LWP::Protocol::https::Socket have their parents defined changed from using the @ISA list to use base. However, use base apart from defining the parent(s) of packages also tries loading the classes in question. When using SOAP::Lite and LWP::Protocol::https as an implementor for LWP::Protocol, trying to send an HTTPS request leads to a failure, and the IO::Socket::SSL::SSL_ERROR scalar which technically is meant to contain SSL failure messages contains the following error instead: Can't locate object method "new" via package "LWP::Protocol::https::Socket" at SOAP/Client.pm. The final error is the following:

 Cannot load LWP::Protocol::https: Can't locate LWP/Protocol/http/SocketMethods.pm in <inc_paths>) at base.pm line 105
        ...propagated at base.pm line 159, <STDIN> line 5.

I am using a custom perl + modules distribution, but I have the latest LWP::Protocol::http in @INC and there is no way it doesn't contain the LWP::Protocol::http::SocketMethods package.

This is an excerpt from the code that performs the SOAP::Lite requests (I did my best to keep the code as runnable as possible while getting rid of custom things):

My/Custom/SOAP/Schema.pm:

package SOAP::Schema;
package My::Custom::SOAP::Schema;
use strict;

#
# override access() to get wsdl from a buffer 
#

our @ISA = qw (SOAP::Schema);

sub setWsdlBuf{
    $_[0]->{_wsdlbuf} = $_[1];
}

sub access{
    my $self = shift;
    if ($self->{_wsdlbuf}){
        return $self->{_wsdlbuf};
    }
    return $self->SUPER::access (@_);
}

1;

driver script:

use My::Custom:::SOAP::Schema;
use SOAP::Lite;

our ($wsdlDefinition, $baseUrl, $keepAlive, $timeout, $host, $port, $user, $realm, $password); # imported from elsewhere

require LWP::Protocol::https;
LWP::Protocol::implementor( 'https' => 'LWP::Protocol::https');

my $schema = My::Custom:::SOAP::Schema->new();
$schema->setWsdlBuf($wsdlDefinition);
my $soapLiteObj = SOAP::Lite->new();
$soapLiteObj->schema($schema);
local $SIG{__WARN__} = sub {};
my $soapLiteService = $soapLiteObj->service($baseUrl);

my $ssl_opts = {
# some properties like cert file path and hostname verification
};

my $credentials = [
    "$host:$port",
    $realm,
    $user,
    $password
];

my $service = $soapLiteService->proxy(
    $baseUrl,
    'keep_alive' => $keepAlive,
    'timeout'=> $timeout,
    'credentials' => $credentials,
    'ssl_opts' => [%$ssl_opts]
);

$service->on_fault (
    sub {
        my $soap = shift;
        my $res = shift;
        if(!ref($res)) {
            my $error = $soap->transport ()->status ();
            if (defined $IO::Socket::SSL::SSL_ERROR){
                $error .= ":  $IO::Socket::SSL::SSL_ERROR";
            }
            say STDERR "SOAP::Lite error: $error"; # this is where the LWP::Protocol::https error in question is observed
            return;
        }
        return $res->fault();
    }
);

$service->someMethod();

Apart from resolving SOAP::Lite failures for people that have code similar to mine (I'm not sure if there are many because #30 is 7 years old), this change also has the following benefits:

I've been testing this over the course of a month and it seems fairly stable. Feel free to share feedback as well.

mtsanovv commented 7 months ago

Hi @oalders, thanks for the PR approval! Are there any concerns preventing its merge?

oalders commented 7 months ago

No concerns here. I just wanted to see if anyone else had an opinion. I plan to merge and release in the next couple of days.