http://www.perlmonks.org?node_id=1015590

milovidov has asked for the wisdom of the Perl Monks concerning the following question:

Hello all!

I have this code for access to Bing Translation Api vis SOAP protocol:

sub getLanguagesForTranslate { my ($self) = @_; my $token = $self->getAccessToken(); my $soap = SOAP::Lite->proxy('http://api.microsofttranslator.com/V +2/Soap.svc'); $soap->transport->http_request->header('Authorization' => $token); my $answer = $soap->GetLanguagesForTranslate("appId" => ""); return $answer->result; }

My problem is in SOAP contract mismatch. My debug messages from SOAP is:

SOAP::Transport::HTTP::Client::send_receive: POST http://api.microsoft +translator.com/V2/Soap.svc HTTP/1.1 Accept: text/xml Accept: multipart/* Accept: application/soap Authorization: Bearer http%253a%252f%252fschemas.xmlsoap.org%252fws%25 +2f2005%252f05%252fidentity%252fclaims%252fnameidentifier%3DBingTransl +ationTest%26http%253a%252f%252fschemas.microsoft.com%252faccesscontro +lservice%252f2010%252f07%252fclaims%252fidentityprovider%3Dhttps%253a +%252f%252fdatamarket.accesscontrol.windows.net%252f%26Audience%3Dhttp +%253a%252f%252fapi.microsofttranslator.com%26ExpiresOn%3D1359323697%2 +6Issuer%3Dhttps%253a%252f%252fdatamarket.accesscontrol.windows.net%25 +2f%26HMACSHA256%3Dd4RTa2yAxgndSazm3Ikg0H%252bs3k24wua4rXqZvrUP90Y%253 +d Content-Length: 505 Content-Type: text/xml; charset=utf-8 SOAPAction: "#GetLanguagesForTranslate" <?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:xsi="http:/ +/www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xm +lsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema +" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmln +s:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><GetLan +guagesForTranslate><c-gensym3 xsi:type="xsd:string">appId</c-gensym3> +<c-gensym5 xsi:type="xsd:string" /></GetLanguagesForTranslate></soap: +Body></soap:Envelope> SOAP::Transport::HTTP::Client::send_receive: HTTP/1.1 500 Internal Ser +ver Error Date: Sun, 27 Jan 2013 21:44:55 GMT Content-Length: 723 Content-Type: text/xml; charset=utf-8 Client-Date: Sun, 27 Jan 2013 21:44:56 GMT Client-Peer: 131.253.14.99:80 Client-Response-Num: 1 <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Bod +y><s:Fault><faultcode xmlns:a="http://schemas.microsoft.com/ws/2005/0 +5/addressing/none">a:ActionNotSupported</faultcode><faultstring xml:l +ang="en-US">The message with Action '#GetLanguagesForTranslate' canno +t be processed at the receiver, due to a ContractFilter mismatch at t +he EndpointDispatcher. This may be because of either a contract misma +tch (mismatched Actions between sender and receiver) or a binding/sec +urity mismatch between the sender and the receiver. Check that sende +r and receiver have the same contract and the same binding (including + security requirements, e.g. Message, Transport, None).</faultstring> +</s:Fault></s:Body></s:Envelope>

I think that problem in authentication. The fact is that you must first obtain the token from Microsoft OAuth server, and put it into the Http request header (you will can read about it from, for example, GetLanguagesForTranslate Method). You can see this in the "Authorization" row from my debug info. This token getting from getAccessToken method in my code, and i don't have warning about this method. I had tested it earler.

I think, that problem in authentication because if i don't put token into Http request, i will have the same error.

This is my first expirience with SOAP and please tell me when i could make mistake!

Thanks for you attention!

UPDATE

I just tried to run PHP example from microsoft sample and made output SOAP request. It is very intresting and you can see this:

POST /V2/soap.svc HTTP/1.1 Host: api.microsofttranslator.com Connection: Keep-Alive User-Agent: PHP-SOAP/5.4.10 Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f0 +5%2fidentity%2fclaims%2fnameidentifier=BingTranslationTest&http%3a%2f +%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims% +2fidentityprovider=https%3a%2f%2fdatamarket.accesscontrol.windows.net +%2f&Audience=http%3a%2f%2fapi.microsofttranslator.com&ExpiresOn=13593 +95243&Issuer=https%3a%2f%2fdatamarket.accesscontrol.windows.net%2f&HM +ACSHA256=a7cPdve2lE7kF5n3ZMMY8byf3p5SIMfrFpJpZird2Vw%3d Content-Type: + text/xml; charset=utf-8 SOAPAction: "http://api.microsofttranslator.com/V2/LanguageService/Get +LanguagesForTranslate" Content-Length: 1462 Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f0 +5%2fidentity%2fclaims%2fnameidentifier=BingTranslationTest&http%3a%2f +%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims% +2fidentityprovider=https%3a%2f%2fdatamarket.accesscontrol.windows.net +%2f&Audience=http%3a%2f%2fapi.microsofttranslator.com&ExpiresOn=13593 +95243&Issuer=https%3a%2f%2fdatamarket.accesscontrol.windows.net%2f&HM +ACSHA256=a7cPdve2lE7kF5n3ZMMY8byf3p5SIMfrFpJpZird2Vw%3d

You can see that "Authorization" field in HTTP request have duplicate! But, you can see also that "SOAPAction" field have value is "http://api.microsofttranslator.com/V2/LanguageService/GetLanguagesForTranslate".

In my request from SOAP::Lite i had "SOAPAction" called as "#GetLanguagesForTranslate". And now i have a question - how i can change SOAPAction field in my SOAP::Lite request?

UPDATE 2. Solution

After i traced C# sample and when i saw SOAP request i had found a solution. Say the truth i had not made the SOAP::Lite request is equal as C# SOAP request because i had couldn't change http header fully. But it work!

My code now is:

use SOAP::Lite; $SOAP::Constants::DO_NOT_USE_CHARSET = 0; $SOAP::Constants::PREFIX_ENV= "s"; $SOAP::Constants::DEFAULT_XML_SCHEMA = undef; #Other code sub getLanguagesForTranslate { my ($self) = @_; my $token = $self->getAccessToken(); my $soap = SOAP::Lite->proxy('http://api.microsofttranslator.com/V +2/Soap.svc') ->on_action(sub {return + '"http://api.microsofttranslator.com/V2/LanguageService/Ge +tLanguagesForTranslate"'}) ->readable(1) ->encodingStyle("") ->encoding(undef); $soap->transport->http_request->header("Authorization" => $token); my $method = SOAP::Data->name('GetLanguagesForTranslate')->attr({x +mlns => 'http://api.microsofttranslator.com/V2'}); my @params = ( SOAP::Data->name("appId")->type("string")->value("" +)->type("")); my $answer = $soap->call($method => @params); return $answer->result->{string}; } </p>

This page very helped me: How to Call a .NET-based Web Service Using the SOAP::Lite Perl Library.

Replies are listed 'Best First'.
Re: SOAP::Lite contract mismatch error
by Anonymous Monk on Jan 28, 2013 at 02:05 UTC

      Lingua::Translate::Bing is my module :)

      Now, i want refactor it for using SOAP protocol instead of HTTP.

      I tried SOAP::Simple with this code:

      sub getLanguagesForTranslate { my ($self) = @_; my $token = $self->getAccessToken(); my $soap = SOAP::Simple->new('http://api.microsofttranslator.com/V +2/Soap.svc'); my $answer = $soap->GetLanguagesForTranslate("appId" => ""); return $answer->result; }

      But i had this error:

      Remote fetching not implemented yet at /home/Muxa/perl5/lib/perl5/SOAP +/Simple/Trait.pm line 73. SOAP::Simple::Trait::_fetch_wsdl('Moose::Meta::Class::__ANON__::SE +RIAL::1=HASH(0x4332df8)', 'http://api.microsofttranslator.com/V2/Soap +.svc') called at /home/Muxa/perl5/lib/perl5/SOAP/Simple/Trait.pm line + 67 SOAP::Simple::Trait::_coerce_wsdl('Moose::Meta::Class::__ANON__::S +ERIAL::1=HASH(0x4332df8)', 'http://api.microsofttranslator.com/V2/Soa +p.svc') called at /home/Muxa/perl5/lib/perl5/SOAP/Simple/Trait.pm lin +e 12 SOAP::Simple::Trait::add_wsdl('Moose::Meta::Class::__ANON__::SERIA +L::1=HASH(0x4332df8)', 'http://api.microsofttranslator.com/V2/Soap.sv +c') called at /home/Muxa/perl5/lib/perl5/SOAP/Simple.pm line 29 SOAP::Simple::new('SOAP::Simple', 'http://api.microsofttranslator. +com/V2/Soap.svc') called at Lingua/Translation/Bing.pm line 135

        Really? SOAP::Simple is so simple, it doesn't take URLs, it takes filenames, as the synopsis and examples show
Re: SOAP::Lite contract mismatch error
by RichardK (Parson) on Jan 28, 2013 at 00:44 UTC

    try reading the documentation you linked to!

     Authorization    : Required. Specify the the value of access_token in format "Bearer" + " " + Access Token Value

      I have "Authorization" header in my http request. You can see it in my debug information:

      Authorization: Bearer http%253a%252f%252fschemas.xmlsoap.org%252fws%25 +2f2005%252f05%252fidentity%252fclaims%252fnameidentifier%3DBingTransl +ationTest%26http%253a%252f%252fschemas.microsoft.com%252faccesscontro +lservice%252f2010%252f07%252fclaims%252fidentityprovider%3Dhttps%253a +%252f%252fdatamarket.accesscontrol.windows.net%252f%26Audience%3Dhttp +%253a%252f%252fapi.microsofttranslator.com%26ExpiresOn%3D1359323697%2 +6Issuer%3Dhttps%253a%252f%252fdatamarket.accesscontrol.windows.net%25 +2f%26HMACSHA256%3Dd4RTa2yAxgndSazm3Ikg0H%252bs3k24wua4rXqZvrUP90Y%253

      And in the code:

      $soap->transport->http_request->header('Authorization' => $token);