Search code examples
perlsoapwsdl

Getting "A service address has not been specified..." when using Perl SOAP::Lite to do call using wsdl


I'm trying to do a SOAP call to http://www.webservicex.net/ConvertSpeed.asmx using the WSDL.

My code is as follows

use SOAP::Lite;

my $client = SOAP::Lite->new;
$client    = $client->service( "http://www.webservicex.net/ConvertSpeed.asmx?wsdl" );

my $soapResp = $client->call( "ConvertSpeed", 100, "kilometersPerhour", "milesPerhour" );

if ( $soapResp->fault ) {
    print $soapResp->faultstring;
}
else {
    print $soapResp->result;
}

This gives me the following error

A service address has not been specified either by using SOAP::Lite->proxy() or a service description)

I believe that the WSDL is supposed to provide the service address, but it does not seem to be doing that here.

I have tried setting the service address to http://www.webservicex.net/ConvertSpeed.asmx via $client->proxy("http://www.webservicex.net/ConvertSpeed.asmx") after $client->service(), but that just gives me an error saying:

Server did not recognize the value of HTTP header SOAPAction: #ConvertSpeed

I assumed the WSDL was supposed to provide the service address and so omitted the $client->proxy() bit and tried other stuff.

This ranged from chaining methods differently and eventually chaining as little as possible (the code above) to changing the way the call is made.

From this answer I tried

$client->ConvertSpeed(100, "kilometersPerhour", "milesPerhour")

which just seems to return nothing.

This is running on Perl 5.10 and version 0.714 of SOAP::Lite.

I'm not sure what else to try, but I have confirmed that the same SOAP call works from Python(see edit).

EDIT:

from zeep import Client

client = Client('http://www.webservicex.net/ConvertSpeed.asmx?wsdl')
result = client.service.ConvertSpeed(100, 'kilometersPerhour', 'milesPerhour')

print(result)

Solution

  • I posted this question to PerlMonks as well since it didn't seem to be doing well here. According to the answer I received there SOAP::Lite isn't ideal for a complex service using the WSDL. Instead everything should be specified using the uri() and proxy() methods. If the WSDL is to be used then XML::Compile::WSDL11 is the module to look at.

    The answer supplies working code for the call using SOAP::Lite without the WSDL as follows :

    $client = SOAP::Lite->new(
            uri   => 'http://www.webserviceX.NET/',
            proxy => 'http://www.webservicex.net/ConvertSpeed.asmx',
               );
    
    $client->on_action(sub {"http://www.webserviceX.NET/ConvertSpeed"});
    $client->autotype(0);
    $sheader = SOAP::Header->new('');
    $sheader->type(xml => '');
    $client->ns('http://www.webserviceX.NET/','web');
    $client->envprefix('soapenv');
    
    push @request, SOAP::Data->name(speed => 100)->prefix('web');
    push @request, SOAP::Data->name(FromUnit => 'kilometersPerhour')->prefix('web');
    push @request, SOAP::Data->name(ToUnit => 'milesPerhour')->prefix('web');
    
    $soapResp = $client->ConvertSpeed($sheader,@request);
    
    print $soapResp->result,"\n";
    

    If I get a working example using XML::Compile::WSDL11 I will post it here. As I am unsure if I am going to look into it soon I decided to at least post this since the question is more focused on using a WSDL with SOAP::Lite