Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SOAP client timeouts during function execution

I need to use SOAP to retrieve some data from a database. I'm not an experienced PHP programmer, that's why I need some help. The company which provides the webservice (WSDL) gave me login info and links to the svc and wsdl files. They also gave me an example in C# of how to connect:

var proxy = new ChannelFactory<ServiceReferenceWCF.IWebService2>("custom");
            proxy.Credentials.UserName.UserName = login;
            proxy.Credentials.UserName.Password = pass;
            var result = proxy.CreateChannel();
            var logged_in = result.loggedIn();

Here's my PHP code:

$wsdl_proto = 'https';
$wsdl_host = 'their_wsdl_host';
$wsdl_host_path = 'their_wsdl_path';
$namespace_proto = 'https';
$namespace_host = 'their_namespace_host';
$namespace_path = 'their_namespace_path';
$location = $namespace_proto.'://'.$namespace_host.$namespace_path;
$wsdl_url = $wsdl_proto.'://'.$wsdl_host.$wsdl_host_path;
$connection = new SoapClient($wsdl_url, array('location' => $location, 'soap_version' => SOAP_1_1, 'connection_timeout'=> 600,
    'proxy_login' => "my_login", 'proxy_password' => "my_password"));
$functions = $connection->__getFunctions();
var_dump($functions);
$logged_in = $connection->loggedIn();

It hangs during the loggedIn() function call. This function is listed in the $functions variable, so it is valid. I tried some other functions provided by the service - the result is always the same: the script simply freezes. And by that I mean there is no response from the service and PHP waits for the loggedIn() function to finish. After it exceeds the timeout, I get an error: Error Fetching http headers in... What am I doing wrong? How can I debug it?

UPDATE:

I tried every single thing you guys suggested. But I still didn't manage to solve the problem. I don't use a proxy. You can find the results below:

1. I installed the SoapUI. After configuring the request for the some_method function (creating a basic Auth with credentials) I received a response: An error occurred when verifying security for the message. Ticking the Authenticate pre-emptively option didn't help. I searched for a solution to this error, but I didn't find anything.

2. I tried almost every imaginable combination of options for the SoapClient class. Here are some of them:

$connection = new SoapClient($wsdl_url, array(
    'login' => "login",
    'password' => "pass",
    'trace' => 1,
));

The response headers are empty. The request headers:

REQUEST HEADERS:
POST /file.svc HTTP/1.1
Host: host
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.6.16
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://tempuri.org/file/some_method"
Content-Length: 221
Authorization: Basic HASH


REQUEST:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/"><SOAP-ENV:Body><ns1:some_method/></SOAP-ENV:Body></SOAP-ENV:Envelope>

Next combination:

$connection = new SoapClient($wsdl,array(
    'login' => "login",
    'password' => "pass",
    'trace' => 1,
    'connection_timeout' => 500000,
    'cache_wsdl' => WSDL_CACHE_BOTH,
    'keep_alive' => false,
));

The response headers are empty. The request headers are the same, as before.

3. Using this:

$connection->__setLocation('https://host.org/file.svc');

doesn't help. However when I set the location to the WSDL file instead of the SVC file, I get the following response:

HTTP/1.1 405 Method Not Allowed
Connection: Keep-Alive
Content-Length: 1293
Date: Wed, 23 Dec 2015 14:28:53 GMT
Content-Type: text/html
Server: Microsoft-IIS/7.5
Allow: GET, HEAD, OPTIONS, TRACE
X-Powered-By: ASP.NET

I'm sure that the WSDL service is not slow enough, to exceed the timeout (Ricardo Velhote suggested it).

4. I've got an XML configuration file provided with the C# example I mentioned earlier:

<client>
    <endpoint address="https://host/file.svc" binding="customBinding" bindingConfiguration="custom" contract="ServiceReference1.file" name="custom" />
</client>

<bindings>
    <customBinding>
        <binding name="custom">
            <security defaultAlgorithmSuite="Default" authenticationMode="UserNameOverTransport" requireDerivedKeys="true" includeTimestamp="true" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
                <localClientSettings detectReplays="false" />
                <localServiceSettings detectReplays="false" />
            </security>
            <textMessageEncoding messageVersion="Soap11WSAddressing10" />
            <httpsTransport maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" />
        </binding>
    </customBinding>
</bindings>

I tried to extend the SoapClient class as suggested here, but as you can guess it didn't work - the behaviour of the script is still the same.

like image 803
Tomasz Kasperczyk Avatar asked Dec 09 '15 15:12

Tomasz Kasperczyk


1 Answers

According to your update and the XML configuration file provided with the example this Webservice appears to be using WS-Addressing so the regular SOAPClient will not work and requires it to be extended in order to support WS-Addressing.

This is the line that gives it away

<textMessageEncoding messageVersion="Soap11WSAddressing10" />

I have yet to use WS-Addressing but I was recently analysing an API for project we will be working on in the future that requires it.

Please take note of this project or this other project which may be useful (it's easy to search for more PHP WS-Addressing).

Again, I have only done research and do not have any hands-on experience to help you with actual code :)


[EDIT: Obsolete answer after the update]

First of all, you might be being mislead by the use of the variable proxy in the example code. They are probably referring to HTTP Basic Authentication and not a proxy.

Try replacing proxy_login and proxy_password with login and password.

However, having said that, if you are getting the WSDL it means that at least it's connecting and obtaining the information about the service (which is good).

In normal situations you do not need to specify location in SoapClient as it should be defined by the WSDL file. By setting the location parameter you are overriding what is set in the WSDL file and you may be pointing it to a location that does not exist.

Try ommiting the location and soap_version from the SoapClient constructor and let the library handle those parameter automatically:

$connection = new SoapClient($wsdl_url, array('connection_timeout'=> 600,
    'proxy_login' => "my_login", 'proxy_password' => "my_password"));

On the other hand, perhaps you are dealing with an extremely slow Web Service. There are many parameters in PHP that may be affecting the time it takes to timeout and most likely they are well below your connection_timeout parameter:

  • default_socket_timeout
  • max_execution_time
like image 76
Ricardo Velhote Avatar answered Sep 30 '22 07:09

Ricardo Velhote