I’ve been trying to implement SOAP services with my app and I’m running out of ideas to fix a problem. I have my controller set up as follows;
<?php
class SoapController extends CController
{
public function actions()
{
return array(
'quote'=>array(
'class'=>'CWebServiceAction',
),
);
}
/**
* @param string the symbol of the stock
* @return float the stock price
* @soap
*/
public function getPrice($symbol)
{
$prices=array('IBM'=>100, 'GOOGLE'=>350);
return isset($prices[$symbol])?$prices[$symbol]:0;
//...return stock price for $symbol
}
}
?>
In a different controller I have the following method
public function actionApiTest()
{
$client = new SoapClient('http://www.mydomain.com/soap/quote');
return;
}
and I keep running into this error;
SoapFault
Description
SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://www.mydomain.com/soap/quote' : Premature end of data in tag html line 2
Source File
/var/www/vhosts/mydomain.com/httpdocs/protected/controllers/AjaxController.php(147)
00135: if($poll->is_rating == 'true') {
00136: $ret['image'] = Yii::app()->request->baseUrl . $poll->Style->image_file;
00137: }
00138:
00139: echo CJSON::encode($ret);
00140: return true;
00141: }
00142: }
00143:
00144:
00145: public function actionApiTest()
00146: {
00147: $client = new SoapClient('http://www.mydomain.com/soap/quote');
00148: return;
00149: }
00150: }
00151:
00152: ?>
Stack Trace
#0 /var/www/vhosts/mydomain.com/httpdocs/protected/controllers/AjaxController.php(147): SoapClient->SoapClient('http://www.simp...')
#1 /var/frameworks/yii-1.1.1/framework/web/actions/CInlineAction.php(32): AjaxController->actionApiTest()
#2 /var/frameworks/yii-1.1.1/framework/web/CController.php(300): CInlineAction->run()
#3 /var/frameworks/yii-1.1.1/framework/web/CController.php(278): CController->runAction(Object(CInlineAction))
#4 /var/frameworks/yii-1.1.1/framework/web/CController.php(257): CController->runActionWithFilters(Object(CInlineAction), Array)
#5 /var/frameworks/yii-1.1.1/framework/web/CWebApplication.php(320): CController->run('apitest')
#6 /var/frameworks/yii-1.1.1/framework/web/CWebApplication.php(120): CWebApplication->runController('ajax/apitest')
#7 /var/frameworks/yii-1.1.1/framework/base/CApplication.php(135): CWebApplication->processRequest()
#8 /var/www/vhosts/simpoll.biz/httpdocs/index.php(16): CApplication->run()
#9 {main}
My apologies, the url is correct, I editied the domain before posting it on this forum.
I have tried setting up a simple script in PHP that is nothing to do with the Yii install using the following code
<?php
ini_set('display_errors','on');
$client = new SoapClient('http://www.mydomain.com');
echo $client->getPrice('GOOGLE');
?>
The resulting PHP error code follows...
Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://www.mydomain.com' : Premature end of data in tag html line 2 in /var/www/vhosts/mydomain.com/httpdocs/soaptest.php:3 Stack trace: #0 /var/www/vhosts/mydomain.com/httpdocs/soaptest.php(3): SoapClient->SoapClient('http://www.mydo...') #1 {main} thrown in /var/www/vhosts/mydomain.com/httpdocs/soaptest.php on line 3
On the server side you can enable file logging and look for hints in the log file (less probable).
Consider temporarily adding trace calls to the web service classes of the framework.
My own code seems to run fine on 1.1.1 (svn) but I noticed a similar error if I used the wrong url format (path instead of get). In your case something like this: <yourserver>/soap/quote vs <yourserver>/index.php?r=soap/quote.
Personally I use to capture and analyze some network packets in cases like this, then decide what to do next.
For anyone experiencing this problem I have found the cure.
The issue was resolving the domain name. I develop on a virtual machine using my hosts file on my windows machine handle the resolving to the VM’s. This is where the problem was found. The Soap client was obviously not using my windows hosts file to resolve the domain but its internal hosts file (/etc/hosts on linux), so, once I added the entry there, the problem went away.
I tried your script above. Works on both 5.3.1 (openSuse) and 5.2.4 (Ubuntu). It seems like you have some problem in your VM box. Since you are only using SoapClient it’s not Yii related at all.
Edit: On second thought it might be Yii related if there’s - according to your error message - some newer “DTD” Yii doesn’t support. (I don’t know the exact meaning of “DTD” in this context.)
BTW While testing, you should change the wsdl cache ttl.
Update: ini_set(soap.wsdl_cache_enabled, ‘0’) in your script did not work for me. Had to change php.ini, then the wsdl was fetched again.
I have finally uncovered the problem causing this to fail.
The problem is threefold. Firstly, my htaccess appeared to be causing an issue so I now have
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
Secondly, I had a ‘baseUrl’ paramater set in the request component of my main.php config file that caused a conflict.
The final obstacle I came across was again with the request component. If I enable csrf validation then the service runs into a CHttpException - where the log states ‘The CSRF token could not be verified’.
Is there a way to get around this and disabled CSRF validation for the controller running the Soap service?