7

So the error is:

PHP Fatal error: Procedure 'sup:set_availability' not present in XMLSoapServer.php

I am receiving this error on my development environment (MAMP).

This is caused by an invalid XML string, in wich the 'sup' namespace isn't defined:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAPSDK1="http://www.w3.org/2001/XMLSchema" 
    xmlns:SOAPSDK2="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:SOAPSDK3="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <sup:set_availability>
            <SetAvailability>
                ...
            </SetAvailability>
        </sup:set_availability>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

(It's an external request, so I can't just go and correct the source - well I can, but atleast not on a short notice.)

The problem is that I got 2 servers that are processing the same request. Without the error. So my quest is to find out why :)

Some details:

  • Server 1: php 5.3.2
  • Server 2: php 5.4
  • Development: php 5.4

Things I have checked so far:

  • the code is the same svn-checkout
  • no hidden dev or production only setting
  • apache config's are the same
  • wsdl caching is disabled, cached wsdl are cleared
  • php.ini settings are the same, with an exception for libxml2:

Server 1 has version 2.6.26 server 2 has version 2.7.7 - on which the request works like a charm My dev environment has lixml2 version 2.8.0 - and does throw the fatal error.

My guess is (or was) that libxml2 is causing the errors - but I can't find any resource on this topic - neither was I succesfull to downgrade my local libxml2 version to 2.6 or 2.7.

So... any thoughts on this?

Rob Gordijn
  • 6,381
  • 1
  • 22
  • 29
  • Did you disable caching and clear cached wsdl on all 3 servers or just your development server? Perhaps server 1 & 2 are using a cached version where this issue is not present? – FuzzyTree May 09 '14 at 21:32
  • Disabled an cleared on both servers; didn't fix the problem. – Rob Gordijn May 12 '14 at 07:23

4 Answers4

2

I don't know what the problem is ... but since the native PHP SoapClient always seemed a bit "opaque" to me, I like to use the Dklab_SoapClient library.

It uses Curl to retrieve Soap data and it is much more flexible than the native PHP class. Plus you can even extends it to add your own functionnaly if you need too :) I am guessing it would solve your problem.

However, if you dont want to use an external library, I don't have a clue what might cause this ...

Lovau
  • 537
  • 2
  • 5
2

I think missing variable in passed to soap client.Check with with soap client working or not

Kamal
  • 796
  • 7
  • 11
2

I'll suggest a different angle for fixing this problem.

Instead of breaking your XML parser you could modify the request before giving it to your XML parser. Add the sup namespace to the request if it isn't present. Preferably push this change to production and update/fix your production XML parsers.

Once the external source gets their software working remove this hack.

Lindlof
  • 2,152
  • 2
  • 17
  • 26
  • I forgot to mention; beside the 'sup' namespace there are multiple (like 20 to 30) namespace errors like the sup error. So adding all those exception isn't a very nice thing to do. the user 'hakre' is also presenting this solution; it works, but is not the most favorable thing to do. – Rob Gordijn May 12 '14 at 08:28
0

This sounds like a problem with the server configuration. The WSDL URI might be wrong for your development machine so that when the soapserver introspecs itself to the WSDL it can not find that function because it is looking into a wrong server.

The XML though still is wrong as the namespace prefix remains undefined. I would not expect it to safely work as this is no valid XML and valid XML is required for SOAP to work.

A quick test with LIBXML 2.9.1 revealed that the faulty XML chunk is loaded by DOMDocument with a warning but preserved (including the prefix). If you get access to the underlying request document, you can add it your own:

// just test code to mock a DOMDocument having the fault XML from question
$doc  = new DOMDocument();
$back = libxml_use_internal_errors(TRUE);
$doc->loadXML($xml);
libxml_use_internal_errors($back);

// poc to add the prefix definition
$doc->documentElement->setAttributeNS(
    'http://www.w3.org/2000/xmlns/', 'xmlns:sup', 'sup:uri'
);

The document then is:

<SOAP-ENV:Envelope xmlns:SOAPSDK1="http://www.w3.org/2001/XMLSchema" 
        xmlns:SOAPSDK2="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:SOAPSDK3="http://schemas.xmlsoap.org/soap/encoding/" 
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:sup="sup:uri">
    <SOAP-ENV:Body>
        <sup:set_availability>
            <SetAvailability>
                ...
            </SetAvailability>
        </sup:set_availability>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

As you can see the prefix definition has been added. You can intercept the incomming request before SoapServer::handle(), change it and inject it into handle($soap_request).

  • SOAP action: $_SERVER['HTTP_SOAPACTION']
  • Request body: file_get_contents( 'php://input')
  • See: SoapServer::handle()
hakre
  • 193,403
  • 52
  • 435
  • 836