0

I am trying to make simple API call (at least that's what I thought initially when I started ) using SOAP::Lite module. I am using one of the publicly available SOAP API here to add two numbers. I am getting following error:

Server did not recognize the value of HTTP Header SOAPAction: http://tempuri.org/#Add.

I enabled the debug in SOAP::Lite and it seems my request is not formed correctly. I suspect the type specified (xsi:type="xsd:int") in intA and intB is causing issue.

Request from debug:

<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope
    soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">   
  <soap:Body>
    <Add xmlns="http://tempuri.org/">
      <intA xsi:type="xsd:int">5</intA>
      <intB xsi:type="xsd:int">10</intB>
    </Add>   
 </soap:Body> </soap:Envelope>

Here is my Perl code:

#!/usr/bin/env perl

use strict;
use warnings;
use SOAP::Lite;
#use SOAP::Lite +trace => 'all';    

    SOAP::Lite->import(trace => 'debug');

    #my $uri = 'http://tempuri.org/';
    my $proxy = 'http://www.dneonline.com/calculator.asmx';
    my $ns = 'http://tempuri.org/'; 

    my $client = SOAP::Lite
            ->readable(1)
            ->uri($ns)
            ->proxy($proxy);

    my $param1 = SOAP::Data->name("intA" => $x);
    my $param2 = SOAP::Data->name("intB" => $y);

    my $response = $client->Add($param1,$param2);

    print "Result is $response \n";

Note: I tried loading the WSDL in SOAPUI tool and the API works fine there.

UPDATE

As @simbabque suggested, I tried debuging using LWP::ConsoleLogger

Header looks like this:

.---------------------------------+-----------------------------------------.
| Request (before sending) Header | Value                                   |
+---------------------------------+-----------------------------------------+
| Accept                          | text/xml, multipart/*, application/soap |
| Content-Length                  | 549                                     |
| Content-Type                    | text/xml; charset=utf-8                 |
| SOAPAction                      | "http://tempuri.org/#Add"               |
| User-Agent                      | SOAP::Lite/Perl/1.27                    |
'---------------------------------+-----------------------------------------'

I have no idea where # is coming from. Maybe I will try SOAP::Simple and see if it helps.

Cheers

rjx5
  • 3
  • 4
  • 1
    The `#` looks odd. Do you know where that is coming from? – simbabque Oct 09 '18 at 08:47
  • SOAP::Lite uses LWP under the hood. LWP::ConsoleLogger might be a good debugging aid. – simbabque Oct 09 '18 at 08:47
  • Hi @simbabque, Thanks for your reply. I have added the header info from LWP::ConsoleLogger. I see the # sign everywhere with uri in the trace. Not sure, where its coming from. – rjx5 Oct 09 '18 at 19:40
  • If you can pick what you want to use, take a look at XML::Compile::SOAP. It has a bit of a learning curve, but it's actually quite nice. – simbabque Oct 10 '18 at 08:32
  • thanks @simbabque, I will give it a try too. – rjx5 Oct 10 '18 at 22:41

1 Answers1

0

URI and method name (Add) are concatenated to build an http header named SOAPAction.

URI must end with "/". SOAP::Lite merge them with "#".

Long time ago I got the same problem. Found that .NET based webservices are disappointed to see "#" and read about this solution - from man pages - by mean of on_action handler which simply concatenates URI and method name. All this is well documented in man SOAP::Lite

my $client = SOAP::Lite->new(
  readable => 1,
  # uri is the same as package/class name into cgi file; must end with "/"
  uri => $ns, 
  # on action corrects SOAPAction to make .NET happy. .NET dislike the '#' 
  # $_[1] will contain method name on $client->call('someMethName')
  on_action => sub { return '"'. $ns . $_[1] .'"'; },  
  # proxy is the full resource URL of aspx/php/cgi/pl wich implements method name 
  proxy => $proxy);
# rest of your code...
ulix
  • 274
  • 1
  • 2
  • 13
  • Thanks @ulix, I overlooked the on_action method. It works after adding this. `$client->on_action( sub { join '', @_ } );` – rjx5 Oct 10 '18 at 22:39