Вызов простого API-интерфейса Soap с использованием Perl's Soap::Lite

Я пытаюсь сделать простой вызов API (по крайней мере, так я думал, когда начинал), используя модуль SOAP::Lite. Я использую один из общедоступных SOAP API здесь, чтобы добавить два числа. Я получаю следующую ошибку:

Сервер не распознал значение HTTP-заголовка SOAPAction: http://tempuri.org/.

Я включил отладку в SOAP::Lite, и, похоже, мой запрос сформирован неправильно. Я подозреваю, что указанный тип (xsi:type="xsd:int") в intA и intB вызывает проблему.

Запрос отладки:

<?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>

Вот мой Perl-код:

#!/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";

Примечание. Я попытался загрузить WSDL в инструмент SOAPUI, и там API работает нормально.

ОБНОВИТЬ

Как подсказал @simbabque, я попытался отладить, используя LWP::ConsoleLogger

Заголовок выглядит так:

.---------------------------------+-----------------------------------------.
| 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                    |
'---------------------------------+-----------------------------------------'

Я понятия не имею, откуда # идет. Может быть, я попробую SOAP::Simple и посмотрю, поможет ли это.

ура

1 ответ

Решение

URI и имя метода (Add) объединяются для создания заголовка http с именем SOAPAction.

URI должен заканчиваться на "/". SOAP::Lite объединяет их с "#".

Давным-давно у меня возникла такая же проблема. Обнаружил, что веб-сервисы на основе.NET разочарованы тем, что увидели "#" и прочитали об этом решении - со справочных страниц - с помощью обработчика on_action, который просто объединяет URI и имя метода. Все это хорошо документировано в 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...
Другие вопросы по тегам