At my office I can connect directly to the relevant soap servers and my code works as it should.
However - because of security - it is not allowed that VPN connections (from home) access the SOAP servers. So I have to resort to using an SSH tunnel over a jump-station.
Because the WSDL files contain absolute urls I can't use the "location" to change this, it won't load the WSDL. Therefor I've resolved to adding entries to the hosts files mapping that server name to 127.0.0.1 and and SSH tunnel to our jumpstation forwarding the correct ports.
This allows me to use the original WSDL without modification. I just have to comment out the hosts entries when at the office.
Via SoapUI everything works. I can load the WSDL, it fully parses it (it has a lot of includes - big corporate soap service) and I can launch SOAP requests that get answered correctly.
However, if I do the same via the php SoapClient (running against an apache on localhost) it throws an exception:
SOAP-ERROR: Parsing Schema: can't import schema from 'http://wsdl.service.addres:port/wsdlUri?SCHEMA%2Fsoa.osb.model%2Fsrc%...'
(I've replaced the server and the rest of the request because its not relevant.)
If I take that entire URL and paste it into my browser it results in an WSDL-XML.
The PHP code to load create the SoapClient is as simple as this:
$options =
[
'trace' => 1,
'exception' => 1,
];
$wsdl = '/path/to/local/wsdlfile.xml';
$client = new \SoapClient($wsdl, $options);
Anyone have a clue where to look? I can't think of anything to try anymore.
I know for sure that my PHP is setup correctly (as the code has been working for months at the office and nothing was changed here). Is PHP doing DNS resolving differently and somehow getting another (or no) IP for that corporate server perhaps?
Related
I have a VERY simple PHP code:
<?php
$soap = new SoapClient('https://rev-int.api.us.fleetmatics.com/Vehicle/SageQuest/VehicleService.svc?wsdl', array());
var_dump($soap);
When I copy that URL into my browser it loads just fine, with no redirects or anything:
$soap = new SoapClient('https://rev-int.api.us.fleetmatics.com/Vehicle/SageQuest/VehicleService.svc?wsdl
But when I execute that PHP script I get the following error after a PHP timeout:
Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://rev-int.api.us.fleetmatics.com/Vehicle/SageQuest/VehicleService.svc?wsdl=wsdl0' : failed to load external entity "http://rev-int.api.us.fleetmatics.com/Vehicle/SageQuest/VehicleService.svc?wsdl=wsdl0"
Notice the response URL is http://rev-int.api.us.fleetmatics.com/Vehicle/SageQuest/VehicleService.svc?wsdl=wsdl0 which is very similar but not quite accurate. If I search the working WSDL for that given URL I find it at the top:
That said, every URI points to HTTP instead of HTTPS, but if we simply change this in our browser the page loads just fine.
So the question becomes: when we create a PHP SoapClient, can we force all URIs to follow HTTPS regardless of the protocol specified in the WSDL?
The WSDL can stand by itself and contain everything inside, or it can use imports to bring in content from other locations (it usually happens with XSD schemas).
If it imports things, those imports need to be resolved by the client. If they can't be resolved, either because the location is wrong, or the protocol is wrong, or whatever, then the client bails out, because it needs a complete WSDL to understand the service's contract and how to call it, not just the parts it could load.
So you have two options:
Contact the provider of the service and ask them to fix it so all imports can be resolved.
If you can download the WSDL and all the resources it tries to import, by opening in browser and changing the protocol to https, you can save them all locally on disk in the same folder. Assuming you end up with a file named VehicleService.wsdl for the WSDL itself, and VehicleService.xml for the file you got from http://rev-int.api.us.fleetmatics.com/Vehicle/SageQuest/VehicleService.svc?wsdl=wsdl0 somehow, you can then change the WSDL to import this local file with <wsdl:import .... location="VehicleService.xml" /> instead of what it does right now. Then you can feed this local WSDL to your client, and because now everything is in the same folder, it should work.
I have one problem in ONE host: I cannot access an HTTP url (say, http://foo-bar.com:9999/Path/To/My/Soap.svc?wsdl).
Hitting such URL from my localhost (running PHP 5.4) works fine. However, hitting such url from my target server (running PHP 5.5) brings me this SoapFault:
Parsing WSDL: Couldn't load from 'http://foo-bar.com:9999/Path/To/My/Soap.svc?wsdl' : failed to load external entity "http://foo-bar.com:9999/Path/To/My/Soap.svc?wsdl"
(I did not disclose the URL due to contract policies)
What can I check? (Since the url is not in HTTPS but just HTTP, openssl should be discarded)
Code:
new SoapClient(
'http://foo-bar.com:9999/Path/To/My/Soap.svc?wsdl',
array('uri' => 'http://foo-bar.com/wsdl/schema/')
);
Found it: There's nothing wrong in the SOAP client between PHP versions. They remain compatible between -at least- 5.2 and 5.5. So there's nothing weird to test here, but just simple connection tests.
Issues like this should be tested with: file_get_contents('http://foo-bar.com:9999/Path/To/My/Soap.svc?wsdl') (modern PHP versions have fopen_wrappers active by default).
The answer? Connections are refused. That's why I get such error.
I'm working on a project with ZF in windows environment (using wamp) trying to develop a web service (wsdl definition) with the Soap library of Zend.
Everything works as expected at localhost, the URI http://localhost/mySite/webService/Server.php?wsdl returns a good definition of the service and it can be consumed. But the same using an IP like, let's say http://192.168.1.20/mySite/webService/Server.php?wsdl doesn't seem to be available. I get the error:
Forbidden
You don't have permission to access /mySite/webService/Server.php on this server.
I did the test using http://192.168.0.20/mySite/public/ and it works fine. I get the standard "Welcome to the Zend Framework!" because I haven't changed it yet (it even works using my public IP). In the same project I have some controllers/actions and they fail the same way.
I think the problem could be related with the httpd.conf file, but I don't really know how to handle it. Or maybe the .htaccess on this project?
Has somebody a clue?
Thanks.
Try without cache in your client:
$options['cache_wsdl'] = WSDL_CACHE_NONE:
$uri = http://192.168.1.20/mySite/webService/Server.php?wsdl;
$client = new Zend_Soap_Client($uri, $options);
I have a php Soap webservice and a perl script that needs to call it.
But it returns the error
Parsing WSDL: Couldn't load from 'http://xxxxxx:8888/index.php/backup/index' :
failed to load external entity "http://xxxxxx:888/index.php/backup/index"
xxxxx is the dynamic hostname of my server.
IF i call the webservice from localhost with
$client=new SoapClient('http://localhost:8888/index.php/backup/index',array('trace' => 1));
If works fine, but if i try
$client=new SoapClient('http://xxxx:8888/index.php/backup/index',array('trace' => 1));
It gives me that error.
So the problem is that the remote script call the webservice with his hostname, and the webservice cannot resolve that.... how can I solve this?
Found the problem. It's inside the yii class CWebService.
It seems that is unable to resolve the name of the local host...it will always fail if called from an external host.
I resolved it forcing the name to the ip of the server in /etc/host, like
127.0.0.1 www.website.com
I´m a newbie to soap in php, so I apologize if I´m not precise in my description.
I have working soap clients consuming wsdl´s in a providers remote server (eg www.remoteaddress.com/wsdl/webservice.wsdl). I was wondering if I could speed up that first wsdl call (before getting it into de cache) by downloading that wsdl from the remote server and uploading it locally to the same folder that contains the php that makes the call.
php.net says...
$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
'uri' => "http://test-uri/",
'style' => SOAP_DOCUMENT,
'use' => SOAP_LITERAL));
So, questions please...does the location always have to be an http address or can a local apache server address be used (so as to reference a folder on a higher level than the public_html)? or in other words how do I reference in "location" the folder containing the the local uploaded wsdl? Would this speed things up, and if the local wsdl is in a public directory in my local server, does that pose some sort of security risk? Tried some combinations with the localhost above but none worked...
Thanks in advance for your help,
Pablo