Home > Software engineering >  Perl LWP cannot connect to localhost on Windows 11
Perl LWP cannot connect to localhost on Windows 11

Time:07-22

I'm writing a small Perl script to test an API in a local dev environment. I am using Strawberry Perl on Windows 11. The application is in ASP.NET MVC.

When I run it, I get the following error:

500 Can't connect to localhost:44311 (Bad file descriptor)

The full code I've written so far is this:

#!/usr/bin/perl
use warnings;
use v5.20;
use LWP;
use LWP::UserAgent;

use IO::Socket::IP;                                             # needed for "AF_INET"
@LWP::Protocol::http::EXTRA_SOCK_OPTS = ( Family => AF_INET );
@LWP::Protocol::https::EXTRA_SOCK_OPTS = ( Family => AF_INET );  # force IPv4 (doesn't seem to work)

use JSON;

# check socket is open
use IO::Socket::INET;
my @hosts = qw/ localhost:44311 /;
foreach my $host ( @hosts ) {
    my $open = defined IO::Socket::INET->new(PeerAddr => $host, Timeout => 5) || 0;
    printf "Probed %s -> %s \n", $host, $open ? 'ok' : 'NOK';
}
## end check, it is!

my $ua = LWP::UserAgent->new;
$ua->agent("MyApp/0.1 ");

my %get_details = (
    email => 'MY_EMAIL',
   password => 'PasswordOfMine'
);

# Create a request
my $req = HTTP::Request->new(POST => 'https://localhost:44311/api/token');
$req->content_type('application/json');
$req->content( encode_json (\%get_details) );

# Pass request to the user agent and get a response back
my $res = $ua->request($req);

if ($res->is_success) {
    print $res->content;
}
else {
    print $res->status_line, "\n";
}

As you can see, that socket prober I yoink'd from elsewhere reports that Perl can access the socket.

IPv6

I'm aware it may be an IPv6 issue, since LWP defaults to resolve localhost as an IPv6 address and my application runs only on IPv4.

I cannot simply switch 'localhost' for 127.0.0.1 because the application only accepts requests with the correct hostname. If I open 127.0.0.1 in a web browser I get:

Bad Request - Invalid Hostname

so unfortunately that isn't a solution.

Is there any straightforward way to set LWP to resolve 'localhost' as IPv4 only? This would be most welcomed as I'd rather use my choice scripting language to play around with the API.

CodePudding user response:

This fixed it:

$ua->ssl_opts(verify_hostname => 0);

Turns out that it was because the localhost used a self generated certificate and all I had to do was turn off SSL verification.

Thus it wasn't anything to do with IPv6, so I didn't need any of that messing with sockets at the start.

Panic over, thanks anyway!

  • Related