We help IT Professionals succeed at work.

PHP SOAP Uncaught exception - might depend on server settings?

5,161 Views
Last Modified: 2013-11-18
Dear Experts,
I have a problem with a SOAP webservice written in PHP. The webservice is written by me and is used for a stock photography site to give the ability for external applications to upload images to the site.
The code worked perfectly on an old server, it works perfectly in the new dev environment but on production server with the exactly same piece of code I get the following error:
Fatal error: Uncaught SoapFault exception (...)
There shouldn't be any PHP-include errors, as if I call the PHP functions directly, they do the work well, but the same called from an external app or called through a PHP client run on the server this error is returned.
Might this happen because of different system setup or PHP settings? The php.ini, regarding SOAP related functions seem the same. Same PHP and Apache version as well. What other setting should be looked after?
Am chasing the problem in the right direction (server difference?) or this error is probably caused by something completely different?
If needed, I can post here some codes and the WSDL file as well.
Would appreciate any ideas that would come up to your mind, I'm getting pretty clueless. Thank you!
Comment
Watch Question

Richard QuadlingSenior Software Developer

Commented:
Can you show the code generating the exception?

It's going to be a trial and error issue to resolve.

Also, make sure you have the same version of all related dlls/extensions on the live server and of PHP itself.

Run this as info.php

<?php phpinfo(); ?>

on all the servers and check the differences.

Paying attention to SOAP settings.

Make sure the SOAP cache folder exists and you have permissions.

Output for Soap from php -i for me ...

soap

Soap Client => enabled
Soap Server => enabled

Directive => Local Value => Master Value
soap.wsdl_cache => 1 => 1
soap.wsdl_cache_dir => D:\Data\PHP\SOAP_Cache => D:\Data\PHP\SOAP_Cache
soap.wsdl_cache_enabled => 1 => 1
soap.wsdl_cache_limit => 5 => 5
soap.wsdl_cache_ttl => 86400 => 86400


Erm.

That's all I can think of for the time being.
Richard QuadlingSenior Software Developer

Commented:
Hmmm.

Do you use an auto_(ap|pre)pend_file on you dev servers? If so is this configured on the live server?

Author

Commented:
Thank you for your answers!

First of all, we don't use append/prepend files. Otherwise here is a list of differences between dev and production servers I found in PHP, can this indicate you something important maybe?

On production there's eAcc also installed:
with eAccelerator v0.9.5, Copyright (c) 2004-2006 eAccelerator, by eAccelerator

Keep Alive set to ON on dev, OFF on production
Max Requests            Keep Alive: off

extra modules here:
Loaded Modules   mod_info mod_rewrite mod_ssl

HTTP headers:
on dev: Connection       close
on prod: Keep-Alive       timeout=5, max=100
       Connection       Keep-Alive

session values (lifetime, gc_probabilty) are different, though I think those wouldn't make any change

SOAP settings are the same on both boxes, and are the following:
Soap Client       enabled
Soap Server       enabled

Directive      Local Value      Master Value
soap.wsdl_cache_dir      /tmp      /tmp
soap.wsdl_cache_enabled      1      1
soap.wsdl_cache_ttl      86400      86400

Richard QuadlingSenior Software Developer

Commented:
What's in the exception. Can you show the FULL error. It may have nothing to do with config.

For example, file permissions, or DB access or something like that.
Richard QuadlingSenior Software Developer

Commented:
If you've got a URL we can see the error if it is too complicated, then that would be useful.

Author

Commented:
Here is the URL where you can see the whole error message:

http://www.stockxpert.com/plugin/client_delete.php

Richard QuadlingSenior Software Developer

Commented:
Can you show the code for __doRequest(). I would like to see the entire XML being generated and any response you may get.

Author

Commented:
Sure, this is the client:

<?php
  $client = new SoapClient("sxc.wsdl");

  print_r($client->delete("plugintest","1234", "testphoto2.jpg"));
?>

and this is the server:

<?php

require_once ("common_ws.php");
      
function login($username, $password) {
      return ws_login ($username, $password);
}

function upload($username, $password, $title, $caption, $keywords, $filename) {
      return ws_upload ($username, $password, $title, $caption, $keywords, $filename);
}

function delete($username, $password, $files) {
      return ws_delete ($username, $password, $files);
}

ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache

$server = new SoapServer("sxc.wsdl");
$server->addFunction("login");
$server->addFunction("upload");
$server->addFunction("delete");
$server->handle();
?>
Richard QuadlingSenior Software Developer

Commented:
Drilling down ... ws_delete() please?

Author

Commented:
It is in common_ws.php, a usual PHP file containing these functions. If I call those functions separately, they run well, returning the array needed. Just if called as SOAP webservice from the client above it fails. Here is the code for ws_common: (pointed out ... the other two functions in order not to make this post here too long:

<?

require_once ("../common.phtml");
require_once ("../../common.php");
include "iptc_lib.php";

function ws_login ($username, $password) {
...
      }

      function ws_delete ($username, $password, $files) {
            $loginres = ws_login ($username, $password);
      
            if ($loginres['status_num'] != 0)
                  return ($loginres);

            briefcase_chkdir($username);
            $dir=briefcase_getdir($username);

            $files = explode (",",$files);
            if (!is_array ($files))
                  return (array ('status_num' => '10', 'status_msg' => 'No files provided.'));
            foreach ($files as $f) {
                  if (is_file ($dir ."/". $f)) {
                        $fname = $dir ."/" .$f;
                        if (!unlink ($fname))
                              $error = true;
            }
            else {
                        $error = true;
                  }
                  }
            if ($error) {
                  return (array ('status_num' => '10', 'status_msg' => 'Could not delete all files.'));
                  }
            else {
                  return (array ('status_num' => '0', 'status_msg' => 'Successfully removed all files.'));
            }
      }
      
function ws_upload ($username, $password, $title, $caption, $keywords, $filename) {
...
}

?>
Richard QuadlingSenior Software Developer

Commented:
Ah.

SoapClient->__call() - Calls a SOAP function (deprecated)

This method is deprecated. Use SoapClient->__soapCall() instead of it.


I can't tell you when it was deprecated.
Richard QuadlingSenior Software Developer

Commented:
Can you show the wdsl file also.

Author

Commented:
Hmm, but where was the call function in my code...?

Here is the WSDL:

<?xml version ='1.0' encoding ='UTF-8' ?>
<definitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="urn:sxc" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="urn:sxc">
<types>
<xsd:schema targetNamespace="urn:sxc">
  <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
  <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
<xsd:complexType name="Status">
<xsd:all>
  <xsd:element name="status_num" type="xsd:int" />
  <xsd:element name="status_msg" type="xsd:string" />
  </xsd:all>
  </xsd:complexType>
  </xsd:schema>
  </types>
<message name="loginRequest">
  <part name="username" type="xsd:string" />
  <part name="password" type="xsd:string" />
  </message>
<message name="loginResponse">
  <part name="return" type="tns:Status" />
  </message>
<message name="uploadRequest">
  <part name="username" type="xsd:string" />
  <part name="password" type="xsd:string" />
  <part name="title" type="xsd:string" />
  <part name="caption" type="xsd:string" />
  <part name="keywords" type="xsd:string" />
  <part name="base64_photo" type="xsd:string" />
  </message>
<message name="uploadResponse">
  <part name="return" type="tns:Status" />
  </message>
<message name="deleteRequest">
  <part name="username" type="xsd:string" />
  <part name="password" type="xsd:string" />
  <part name="files" type="xsd:string" />
  </message>
<message name="deleteResponse">
  <part name="return" type="tns:Status" />
  </message>
<portType name="sxcPortType">
<operation name="login">
  <documentation>check for login validity</documentation>
  <input message="tns:loginRequest" />
  <output message="tns:loginResponse" />
  </operation>
<operation name="upload">
  <documentation>upload test</documentation>
  <input message="tns:uploadRequest" />
  <output message="tns:uploadResponse" />
  </operation>
<operation name="delete">
  <documentation>delete test</documentation>
  <input message="tns:deleteRequest" />
  <output message="tns:deleteResponse" />
  </operation>
  </portType>
<binding name="sxcBinding" type="tns:sxcPortType">
  <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="login">
  <soap:operation soapAction="urn:sxc#login" style="rpc" />
<input>
  <soap:body use="encoded" namespace="urn:sxc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
  </input>
<output>
  <soap:body use="encoded" namespace="urn:sxc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
  </output>
  </operation>
<operation name="upload">
  <soap:operation soapAction="urn:sxc#upload" style="rpc" />
<input>
  <soap:body use="encoded" namespace="urn:sxc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
  </input>
<output>
  <soap:body use="encoded" namespace="urn:sxc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
  </output>
  </operation>
<operation name="delete">
  <soap:operation soapAction="urn:sxc#delete" style="rpc" />
<input>
  <soap:body use="encoded" namespace="urn:sxc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
  </input>
<output>
  <soap:body use="encoded" namespace="urn:sxc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
  </output>
  </operation>
  </binding>
<service name="sxc">
<port name="sxcPort" binding="tns:sxcBinding">
  <soap:address location="http://stockxpert.com/plugin/sxc_wsdl.php" />
  </port>
  </service>
  </definitions>
Richard QuadlingSenior Software Developer

Commented:
wsdl  file.

Author

Commented:
Actually, sxc_wsdl.php is the server. (sorry for bit messed up naming)
Richard QuadlingSenior Software Developer

Commented:
http://stockxpert.com/plugin/sxc_wsdl.php

Outputs ...

<envelope SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><body><fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>Bad Request. Can't find HTTP_RAW_POST_DATA</faultstring></fault></body></envelope>

What OS and webserver are the servers?

I vaguely remember this being an issue.

Can you check the

; Always populate the $HTTP_RAW_POST_DATA variable.
always_populate_raw_post_data = On

settings on both platforms.

Author

Commented:
; Always populate the $HTTP_RAW_POST_DATA variable.
always_populate_raw_post_data = On

it's commented out on both servers - have a ; before always_populate_raw_post_data = On

The servers are Ubuntu Linux, Apache2, PHP 5.1.2
Richard QuadlingSenior Software Developer

Commented:
Remove the ;

I am pretty sure that there is a way, even uncommented, that this field is NOT populated.

Checking source ...

Richard QuadlingSenior Software Developer

Commented:
From what I can tell, if you are sending the data via POST, then you use $_POST. If you are NOT using POST then you CAN use $HTTP_RAW_POST_DATA which seems wrong to me, but I may be reading that wrong.

Hmm.

soap.c is slightly different.

Can you check your php error log. There should be messages like ...

PHP-SOAP requires 'always_populate_raw_post_data' to be on please check your php.ini file

This will also generate the SOAP fault of ...

soap_server_fault("Server", "Bad Request. Can't find HTTP_RAW_POST_DATA" ...);

So. I think this is the issue.

Author

Commented:
Dear Sage,

sorry for the long delay - in the end there was a solution found to the problem. It wasn't exactly server setting related, but DNS related - due to some misconfiguration, the www.domain... from inside the server wasn't pointing back to the server, but to the load balancer in front of fronteds - this way, the server PHP couldn't be found from the WSDL file. After some configuring of DNS zone files the webservice worked perfectly.
I appreciate all your efforts to help with this, and would happily give you the points on this - however, I wouldn't accept one of your answers which wasn't exactly the solution. Could you advise me please how can I still add points?
Richard QuadlingSenior Software Developer

Commented:
If none of the comments constitute an answer, then you can ask for a refund in Community Support.
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION

Commented:
Can u explain this term "After some configuring of DNS zone files the webservice worked perfectly". What is the configuration u made to work the service fine?
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.