简体   繁体   中英

php soap client, error from bad wsdl? “Uncaught SoapFault exception: [HTTP] Could not connect to host”

I'm mostly new to SOAP, so I made a little test script to connect to my customer's server. They have a GetMessage command in there, that requires no input or authentication and is just intended to test connectivity:

<?php
ini_set('soap.wsdl_cache_enabled',0);
ini_set('soap.wsdl_cache_ttl',0);

$url        = "https://test.mycustomer.com/api/TestService.svc?wsdl";
$client     = new SoapClient($url, array("trace" => 1, "exception" => 0));

$result = $client->GetMessage(NULL);

echo "<pre>".print_r($result, true)."</pre>";
if($result->GetMessageResult->Status == "Success")
{
    echo "Item deleted!";
}
?>

If I run this in the command line I get:

Fatal error: Uncaught SoapFault exception: [HTTP] Could not connect to host in /var/www/my.stage.com/htdocs/common/soaptest.php:8
Stack trace:
#0 [internal function]: SoapClient->__doRequest('<?xml version="...', 'http://459265-d...', 'http://tempuri....', 1, 0)
#1 [internal function]: SoapClient->__call('GetMessage', Array)
#2 /var/www/my.stage.com/htdocs/common/soaptest.php(8): SoapClient->GetMessage(NULL)
#3 {main}
  thrown in /var/www/my.stage.com/htdocs/common/soaptest.php on line 8

And from a browser I get:

PHP Notice: 'SoapClient::__doRequest() [soapclient.--dorequest]: php_network_getaddresses: getaddrinfo failed: Name or service not known' 

In their WSDL for this service, the string "459265" appears here:

<wsdl:service name="TestService">
<wsdl:port name="BasicHttpBinding_ITestService" binding="tns:BasicHttpBinding_ITestService">
<soap:address location="http://459265-dev1/api/TestService.svc"/>
</wsdl:port>
<wsdl:port name="BasicHttpsBinding_ITestService" binding="tns:BasicHttpsBinding_ITestService">
<soap:address location="https://test.mycustomer.com/api/TestService.svc"/>
</wsdl:port>
</wsdl:service>

So my question is, is that correct? Should the WSDL have a local url like that, that I can't get to from my box?

A little more info, when I do a var_dump on __getFunctions and __getTypes, I get

array(2) {
  [0]=>
  string(53) "GetMessageResponse GetMessage(GetMessage $parameters)"
  [1]=>
  string(53) "GetMessageResponse GetMessage(GetMessage $parameters)"
}
array(5) {
  [0]=>
  string(21) "struct GetMessage {
}"
  [1]=>
  string(55) "struct GetMessageResponse {
 string GetMessageResult;
}"
  [2]=>
  string(8) "int char"
  [3]=>
  string(17) "duration duration"
  [4]=>
  string(11) "string guid"
}

What you want to do is wrap your code in a try{}, catch{} block. For example,

<?php
    try {
        ini_set('soap.wsdl_cache_enabled',0);
        ini_set('soap.wsdl_cache_ttl',0);

        $url = "https://test.mycustomer.com/api/TestService.asmx?wsdl";
        $client = new SoapClient($url, array("trace" => 1, "exception" => 0));

        $result = $client->GetMessage(NULL);

        echo "<pre>".print_r($result, true)."</pre>";
        if($result->GetMessageResult->Status == "Success")
        {
            echo "Item deleted!";
        }
    }
    catch (SoapFault $exception) {
        echo $exception->getMessage();
    }
?>

As the error says, Fatal error: Uncaught SoapFault exception: [HTTP] Could not connect to host in .... , so you need to catch the exception in any case. Hope this helps.

Solved it, partially. The problem is in the wsdl service declaration, where it has two ports for the same binding (see above). In php's SoapClient, $location for __doRequest comes from the first binding (forgive me if I'm using the wrong terminology), and the url for that is a local url which is inaccessible to me. So I did this:

class MySoapClient extends SoapClient
{
    public function __doRequest($request, $location, $action, $version, $one_way = 0)
    {
        $response = parent::__doRequest($request, "https://test.mycustomer.com/api/TestService.svc", $action, $version, $one_way);

        return($response);
    }
}

Extending SoapClient and overriding __doRequest, I was able to set $location to the url I knew would work. Ran it again and got the welcome message - yipee! Not a great solution, since I would have to extend a new client for each service, but to fix that all I have to do is take out the hard coded url, replace the local domain in $location with the external domain, and then call __doRequest with that, and it will work with all the services.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM