25

I'm trying to run a web service using PHP & SOAP, but all I'm getting so far is this:

(SoapFault)[2] message which states: 'SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost/MyRegistration/login.xml' : failed to load external entity "http://localhost/MyRegistration/login.xml"

I've tried changing localhost to 127.0.0.1, but that makes no difference. login is actually a wsdl file, but if I put login.wsdl in the SOAPClient constructor, it says "'looks like we got no XML document'" instead.

Here is my code for the SOAP Client (register_client.php):

<?php
try
{
    $sClient = new SoapClient('http://127.0.0.1/MyRegistration/login.wsdl');    

    $param1 = $_POST["regname"];
    $param2 = $_POST["regpass1"];

    $response = $sClient->loginVerify($param1, $param2);    

    var_dump($response);
}
catch(SoapFault $e)
{
    var_dump($e);
}
?> 

And here is the login.wsdl file:

<?xml version="1.0"?>
<definitions name="LoginVal" 
    targetNamespace="urn:LoginVal" 
    xmlns:tns="urn:LoginVal"  
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns="http://schemas.xmlsoap.org/wsdl/">
  <types>
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Login">
  <xsd:element name="getName" type="xsd:string" />
<xsd:element name="getPass" type="xsd:string" />
  <xsd:element name="LoginResponse" type="xsd:string" />          
</xsd:schema>           
  </types>

  <message name="loginVerify">
<part name="username" type="tns:getName" />
<part name="password" type="tns:getPass" />
  </message>

  <message name="doLoginResponse">
<part name="return" type="tns:LoginResponse" />
  </message>  

  <portType name="LoginPort">
    <operation name="loginVerify">
  <input message="tns:loginVerify" />
  <output message="tns:doLoginResponse" />
    </operation>
  </portType>

  <binding name="LoginBinding" type="tns:LoginPort">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
  <operation name="loginVerify">
    <soap:operation soapAction="urn:LoginAction" />
    <input>
      <soap:body use="encoded" namespace="urn:Login" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />         
    </input>
    <output>
      <soap:body use="encoded" namespace="urn:Login" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />         
    </output>
  </operation>
  </binding>

  <service name="LoginService">
    <port name="LoginPort" binding="tns:LoginBinding">
  <soap:address location="http://localhost/MyRegistration/register.php" />
    </port>
  </service>

</definitions>

And I'm not sure if this is involved, so I'm providing the code for the SOAP Server register.php:

<?php
if(!extension_loaded("soap"))
{
    dl("php_soap.dll");
}

ini_set("soap.wsdl_cache_enabled", "0");
$server = new SoapServer("login.wsdl", array('uri'=>'http://127.0.0.1/MyRegistration'))

public function loginVerify($username, $password)
{
    if($_POST["regname"] && $_POST["regemail"] && $_POST["regpass1"] && $_POST["regpass2"] )
    {
        if($_POST["regpass1"] == $_POST["regpass2"])
        {
            $servername = "localhost";
            $username = "root";
            $password = "Hellfire";

            $conn = mysql_connect($servername,$username,"Hellfire")or die(mysql_error());

            mysql_select_db("soap",$conn);

            $sql = "insert into users (name,email,password)values('$_POST[regname]','$_POST[regemail]','$_POST[regpass1]')";

            $result = mysql_query($sql,$conn) or die(mysql_error());

            return "You have registered sucessfully";

            //print "<a href='index.php'>go to login page</a>";
        }
        else return "passwords dont match";
    }
    else return "invalid data";
}

$server->AddFunction("loginVerify");
$server->handle();
?>

I'm sorry if I'm giving unnecessary information, but I'm a complete novice at this - and I'd really appreciate it if someone could point out why exactly this SOAP Fault is being generated, and what I can do to rectify it.

I am using WAMP Server version 2.2, with mySQL 5.5.24 and PHP 5.3.13

MarthyM
  • 1,839
  • 2
  • 21
  • 23
user1743679
  • 351
  • 1
  • 3
  • 3

14 Answers14

34

Security issue: This answer disables security features and should not be used in production!

After migrating to PHP 5.6.5, the soap 1.2 did not work anymore. So I solved the problem by adding optional SSL parameters.

My error:

failed to load external entity

How to solve:

// options for ssl in php 5.6.5
$opts = array(
    'ssl' => array(
        'ciphers' => 'RC4-SHA',
        'verify_peer' => false,
        'verify_peer_name' => false
    )
);

// SOAP 1.2 client
$params = array(
    'encoding' => 'UTF-8',
    'verifypeer' => false,
    'verifyhost' => false,
    'soap_version' => SOAP_1_2,
    'trace' => 1,
    'exceptions' => 1,
    'connection_timeout' => 180,
    'stream_context' => stream_context_create($opts)
);

$wsdlUrl = $url . '?WSDL';
$oSoapClient = new SoapClient($wsdlUrl, $params);
PiTheNumber
  • 22,828
  • 17
  • 107
  • 180
  • 1
    Just to add to the answer, this is motivated by changes in openssl in 5.6.x http://php.net/manual/en/migration56.openssl.php – hlscalon Dec 08 '15 at 13:36
  • 5
    Instead of disabling SSL peer verification, you should attempt to fix whatever makes the validation fail. For example by explicitly setting the path to a cafile which contains the necessary root certs to verify against. The answer gets to the core of the issue though, and sometimes this may be the only solution available, so +1. – deceze Dec 16 '15 at 09:36
  • 1
    Like adding "openssl.cafile=C:/path/to/sslCertificates/cacert.pem" to php.ini :-) (like curl.cainfo !) – François Breton Mar 23 '17 at 15:49
  • Can't find resource for bundle java.util.PropertyResourceBundle, key A SOAP 1.2 message is not valid when sent to a SOAP 1.1 only endpoint. – Rodrigo Prazim Jan 11 '18 at 19:10
13

Security issue: This answer disables security features and should not be used in production!

try this. works for me

$options = array(
    'cache_wsdl' => 0,
    'trace' => 1,
    'stream_context' => stream_context_create(array(
          'ssl' => array(
               'verify_peer' => false,
                'verify_peer_name' => false,
                'allow_self_signed' => true
          )
    ));

$client = new SoapClient(url, $options);
PiTheNumber
  • 22,828
  • 17
  • 107
  • 180
gogagubi
  • 965
  • 1
  • 15
  • 36
12

Put this code above any Soap call:

libxml_disable_entity_loader(false);
Thanh Nguyen
  • 5,174
  • 11
  • 43
  • 74
5

Security issue: This answer disables security features and should not be used in production!

Got a similar response with https WSDL URL using php soapClient

SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from ...

After server has been updated from PHP 5.5.9-1ubuntu4.21 >> PHP 5.5.9-1ubuntu4.23 something went wrong for my client machine osx 10.12.6 / PHP 5.6.30, but MS Web Services Clients connections could be made without issues.

Apache2's server_access.log showed no entry when i tried to load WSDL so i added 'cache_wsdl' => WSDL_CACHE_NONE to prevent client-side wsdl caching, but still got no entries. Finally i tried to load wsdl per CURL -i checked HEADERS but all seemed to be ok..

Only libxml_get_last_error() provided some insight > SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

So I added some ssl options to my call:

$contextOptions = array(
    'ssl' => array(
    'verify_peer' => false,
    'verify_peer_name' => false,
    'allow_self_signed' => true
    ));

$sslContext = stream_context_create($contextOptions);

$params =  array(
    'trace' => 1,
    'exceptions' => true,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'stream_context' => $sslContext
    );

try {
    $proxy = new SoapClient( $wsdl_url, $params );
} catch (SoapFault $proxy) {
    var_dump(libxml_get_last_error());
    var_dump($proxy);
}

In my case 'allow_self_signed' => true did the trick!

PiTheNumber
  • 22,828
  • 17
  • 107
  • 180
c3labs
  • 51
  • 1
  • 2
3

On register_client.php make sure that the URL that has been passed to SoapClient is accessible from the machine you're executing the code.

$sClient = new SoapClient('http://127.0.0.1/MyRegistration/login.wsdl');    

If 127.0.0.0 does not work you can try using some network IP address and see.

Let me know if it still does not fix it for you, I did try with your example and changing path (making it proper in my dev. environment) has fixed same error for me.

I would be interested to know if it does not fix it for you.

deej
  • 2,536
  • 4
  • 29
  • 51
3

I am using selinux and with the following shell command (as root) I was able to allow PHP to make SOAP calls:

sudo setsebool -P httpd_can_network_connect on
Samo
  • 2,093
  • 1
  • 17
  • 18
3

There is a chance you get this error because of OpenSSL's default security level.

You may need to lower seclevel in /etc/ssl/openssl.cnf from DEFAULT@SECLEVEL=2 to DEFAULT@SECLEVEL=1

Or just run

sed -i "s|DEFAULT@SECLEVEL=2|DEFAULT@SECLEVEL=1|g" /etc/ssl/openssl.cnf

Source: https://github.com/dotnet/runtime/issues/30667#issuecomment-566482876

After that change I can run SoapClient without any additional options


You can verify it by running

curl -A 'cURL User Agent' -4 https://ewus.nfz.gov.pl/ws-broker-server-ewus/services/Auth?wsdl
miken32
  • 42,008
  • 16
  • 111
  • 154
GetoX
  • 4,225
  • 2
  • 33
  • 30
  • I spent a whole day trying to fix this issue. I tried your `sed` suggestion, and it worked from the command line, but it didn't fix the problem in my PHP SoapClient config. I had to add `'security_level' => 1` to the SSL `stream_context` setting to do the same thing within PHP. I'm just adding this comment in case someone else gets stuck in the same way. – Gareth Nov 06 '20 at 16:10
2

I had the same problem.

This php setting solved my problem:

allow_url_fopen -> 1
hazard16
  • 65
  • 2
  • 10
2

Just had a similar problem trying to use SoapClient. Everything was working fine but in production, sometimes on page refresh, I would get the "SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from .." error.

I was using the params:

new \SoapClient($WSDL, array('cache_wsdl' => WSDL_CACHE_NONE, 'trace' => true, "exception" => 0)); 

Removing all the params worked for me:

new \SoapClient($WSDL); 
read
  • 340
  • 5
  • 14
1

I had the same problem, I succeeded by adding:

new \SoapClient(URI WSDL OR NULL if non-WSDL mode, [
    'cache_wsdl' => WSDL_CACHE_NONE, 
    'proxy_host' => 'URL PROXY',
    'proxy_port' => 'PORT PROXY'
]);

Hope this help :)

0

If anyone has the same problem, one possible solution is to set the bindto stream context configuration parameter (assuming you're connecting from 11.22.33.44 to 55.66.77.88):

$context = [
    'socket' => [
        'bindto' => '55.66.77.88'
    ]
];

$options = [
    'soapVersion' => SOAP_1_1,
    'stream_context' => stream_context_create($context)
];

$client = new Client('11.22.33.44', $options);
MarthyM
  • 1,839
  • 2
  • 21
  • 23
Shmarkus
  • 178
  • 1
  • 11
-1

The problem may lie in you don't have enabled openssl extention in your php.ini file

go to your php.ini file end remove ; in line where extension=openssl is

Of course in question code there is a part of code responsible for checking whether extension is loaded or not but maybe some uncautious forget about it

Dawid D
  • 1,057
  • 13
  • 28
-1

In my case with docker I just changed localhost (or 127.0.0.1) to 172.17.0.1 in url. This is default IP of docker host when using

networks:
  my-own-network:
    driver: bridge

in docker-compose.yml.

-1

To who else has the same problem, as for myself at the future: I'm having this kind of problem on Ubuntu Server 18 on Oracle Virtualbox and the issue was a netplan config error inside /etc/netplan/00-installer-config.yaml file causing the brigdeg network interface do successfully ping internet addresses but fail to access it through cURL.

I've corrected it changing it to be like this:

enter image description here

Note: that in this case my internet gateway is 192.168.0.1 and the VM interface IP is fixed on 192.168.0.100 then you should change these lines as you wish.

Then run:

netplan apply