Link to home
Start Free TrialLog in
Avatar of aburany
aburany

asked on

PHP SOAP Uncaught exception - might depend on server settings?

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!
Avatar of Richard Quadling
Richard Quadling
Flag of United Kingdom of Great Britain and Northern Ireland image

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.
Hmmm.

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

ASKER

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

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.
If you've got a URL we can see the error if it is too complicated, then that would be useful.
Avatar of aburany

ASKER

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

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

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

ASKER

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();
?>
Drilling down ... ws_delete() please?
Avatar of aburany

ASKER

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) {
...
}

?>
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.
Can you show the wdsl file also.
Avatar of aburany

ASKER

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>
wsdl  file.
Avatar of aburany

ASKER

Actually, sxc_wsdl.php is the server. (sorry for bit messed up naming)
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.

Avatar of aburany

ASKER

; 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
Remove the ;

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

Checking source ...

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.
Avatar of aburany

ASKER

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?
If none of the comments constitute an answer, then you can ask for a refund in Community Support.
ASKER CERTIFIED SOLUTION
Avatar of Computer101
Computer101
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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?