perlstrawberry-perlpar

Strawberry Perl and PAR - run time error on other Windows machine: LWP will support https URLs if the LWP::Protocol::https module is installed


I have two Windows 10 machines, and on one of them, I have installed Strawberry Perl (version 5.30.1 if it matters). My script is using REST::Client, and on this machine, the script runs perfectly.

I'm using PAR to make an .exe

I can run either the .pl script or the .exe executable; on this machine it runs perfectly. I am using the --execute option when I'm running pp.bat, and include an --xargs= option so that the script can execute and run successfully.

Then I copy the .exe to another machine which does not have Perl installed. I launch the .exe with the same command line option, it compiles fine and begins to run. It does some work and then makes the first REST GET. On this machine without Strawberry Perl on it, I get a message "The service reports a permanent error: LWP will support https URLs if the LWP::Protocol::https module is installed."

Then, of course, I get 500 series errors because the REST web service is unhappy about the lack of https:// for the GET.

There is another error, too:

The service reports a permanent error: Can't locate object method "new" via package "LWP::Protocol::https::Socket" at C:\foo\bar\AppData\Local\Temp\baz\qux\inc\lib/LWP/Protocol/http.pm line 34.

In the .bat file which I use to call pp.bat, I do have --module="LWP::Protocol::https" - although it doesn't seem to make a difference if it's there or not.

I see some documentation about LWP::UserAgent and specifying protocols_allowed => ['https'] but I'm not sure about how that should be applied for use in REST::Client. I've tried putting it in (and leaving it out) and my results are the same. That portion of my code looks like this:

    my $client = REST::Client->new();

    $client->addHeader( 'charset',       'UTF-8' );
    $client->addHeader( 'Accept',        'application/xml' );
    $client->addHeader( 'Authorization', $login_string );
    $client->addHeader( 'Content-Type',  'application/xml' );
    $client->getUseragent()->ssl_opts( verify_hostname => 0 );
    $client->getUseragent()->ssl_opts( SSL_verify_mode => 0 );
    $client->getUseragent( protocols_allowed => ['https'] );
    $client->setTimeout( 10 );

    $client->setHost( $host );

    $client->GET( $url );

    my $rest_client_reponse_code = $client->responseCode();

Can anyone see what I'm missing here, and give me a pointer?


Solution

  • According to the maintainer of Par::Packer in this GitHub issue :

    PAR::Packer does not pack these non-Perl DLL dependencies. You can either chase them done and explicitly pack them by hand with pp --link ..., [...]. Or use Shawn Laffan's App::PP::Autolink that does this for you.

    So given this test script p.pl:

    use strict;
    use warnings;
    use LWP::UserAgent;
    
    my $ua = LWP::UserAgent->new();
    my $res = $ua->get( 'https://metacpan.org/pod/pp');
    if ($res->is_success) {
      print "ok\n";
    }
    else {
      die $res->status_line;
    }
    

    You can use App::PP::Autolink like this:

    > pp_autolink -o p5.exe p.pl
    Use of uninitialized value $_ in pattern match (m//) at C:\Strawberry\perl\site\lib/App/PP/Autolink.pm line 127.
    Use of uninitialized value $_ in -e at C:\Strawberry\perl\site\lib/App/PP/Autolink.pm line 128.
    DLL check iter: 1
    DLL check iter: 2
    DLL check iter: 3
    
    Unable to locate these DLLS, packed script might not work:
    
    Alien sys dlls added:
    Detected link list: --link c:\strawberry\c\bin/libssl-1_1-x64__.dll --link c:\strawberry\c\bin/zlib1__.dll --link c:\strawberry\c\bin/libcrypto-1_1-x64__.dll
    CMD:pp --link c:\strawberry\c\bin/libssl-1_1-x64__.dll --link c:\strawberry\c\bin/zlib1__.dll --link c:\strawberry\c\bin/libcrypto-1_1-x64__.dll -o p5.exe p.pl
    

    As you can see from the above output, we were missing libssl-1_1-x64__.dll, zlib1__.dll, and /libcrypto-1_1-x64__.dll. Transferring this p5.exe to the other Windows 10 machine now works fine.