php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73043 WSDL: import schema if WSDL uri does NOT end with a slash
Submitted: 2016-09-07 21:02 UTC Modified: 2016-09-09 14:26 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: filip dot rydlo at gmail dot com Assigned:
Status: Not a bug Package: SOAP related
PHP Version: 5.6.26RC1 OS: Debian 8.5 Jessie x64
Private report: No CVE-ID: None
 [2016-09-07 21:02 UTC] filip dot rydlo at gmail dot com
Description:
------------
When loading WSDL:

PHP SoapClient FAILs to find *.XSD files despite the fact that they are properly defined in the WSDL file downloaded from the server. They are defined like this:

<wsdl:definitions ...
...
<wsdl:types>
  <xsd:schema>
    <xsd:import namespace="http://fs.mfcr.cz/eet/schema/v3"   schemaLocation="EETXMLSchema.xsd"/>
  </xsd:schema>
</wsdl:types>
...

WSDL addr. : https://pg.eet.cz/eet/services/EETServiceSOAP/v3?wsdl

Test script:
---------------
<?php
define('WSDL', 'https://pg.eet.cz:443/eet/services/EETServiceSOAP/v3?wsdl');  // EET srvr NETOLERUJE koncove '/' za "v3"!!!
define('ENDPOINT_LOCATION', 'https://pg.eet.cz:443/eet/services/EETServiceSOAP/v3/');  // NETOLERUJE koncove '/', bacha!

$options= array(
        'cache_wsdl' =>   WSDL_CACHE_NONE,
        'encoding' =>     'utf-8',
        'soap_version' => SOAP_1_1,
        'exceptions' =>   true,
        'trace' =>        1,
        'location' =>     ENDPOINT_LOCATION
);

$test_msg= "<EmptyTest>NODATA</EmptyTest>";
$input_args= new SoapVar($test_msg, XSD_ANYXML);

try
{
        xdebug_disable();
        //-------------------------------------
        $soap= new SoapClient(WSDL, $options);
        //-------------------------------------
        xdebug_enable();


        xdebug_disable();
        $out = $soap->__soapCall('OdeslaniTrzby', array($input_args), $options, null, $output_headers);
        xdebug_enable();

        echo("<br />REQUEST :<br />". htmlspecialchars($eet->__getLastRequest())  ."<br />");
        echo("<br />RESPONSE:<br />". htmlspecialchars($eet->__getLastResponse()) ."<br />");
}
catch (SoapFault $fault)
{
        xdebug_enable();
        echo "Error:<br />" . nl2br($fault->faultcode) . '<br /><br />Error Details:<br />'. nl2br($fault->faultstring) . '<br />';
}


Expected result:
----------------
REQUEST : <dumped-xml-request..........>


In short:
It should successfully import the XSD schema from the correct location - DESPITE the webservice location does NOT end with a slash "/".


In short: It should have looked for it here:

https://pg.eet.cz:443/eet/services/EETServiceSOAP/v3/EETXMLSchema.xsd

NOT here:

https://pg.eet.cz:443/eet/services/EETServiceSOAP/EETXMLSchema.xsd


Actual result:
--------------
PHP Fatal error: SOAP-ERROR: Parsing Schema: can't import schema from 'https://pg.eet.cz:443/eet/services/EETServiceSOAP/EETXMLSchema.xsd' in /home/username/EET/src/testscript.php on line 21
Error:
WSDL

Error Details:
SOAP-ERROR: Parsing Schema: can't import schema from 'https://pg.eet.cz:443/eet/services/EETServiceSOAP/EETXMLSchema.xsd'


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-09-08 04:10 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2016-09-08 04:10 UTC] requinix@php.net
> they are properly defined in the WSDL file
I disagree.

The XSD 1.1 Part 1 specification says [1]
> 4. When schema location values (i.e. schemaLocation attributes on ...<import>...)
> are... relative references, then the [base URI] of the [owner element] must be
> used to resolve the relative references.

In your example, the "owner" is the source WSDL document and the "base URI" is https://pg.eet.cz/eet/services/EETServiceSOAP/v3?wsdl.

Unfortunately uncited in the XSD spec, RFC 3986 is what details [2] how to resolve relative references, and if you're familiar with web development then you should already know that a reference "a" relative to a base "b/c?d" resolves to "b/a", while relative to "b/c/?d" resolves to "b/c/a". The trailing slash is very significant.

Therefore "EETXMLSchema.xsd" relative to "https://pg.eet.cz/eet/services/EETServiceSOAP/v3?wsdl" resolves to "https://pg.eet.cz/eet/services/EETServiceSOAP/EETXMLSchema.xsd". Clearly this is not the intent of the WSDL's author, however PHP is behaving correctly. Can you provide any references to suggest otherwise?

[1] https://www.w3.org/TR/xmlschema11-1/#schema-loc
[2] https://www.ietf.org/rfc/rfc3986.txt section 5.2
 [2016-09-09 12:42 UTC] filip dot rydlo at gmail dot com
>> they are properly defined in the WSDL file
> I disagree.

Oh, NO! This cannot be. Can't be real! Sorry, that I am so shocked. But ... I just can't believe this is happening!!

This WSDL is given to us, developers, by out government! It HAS TO BE correct and absolutely without any error. :-(((

Considering how many millions of dollars it has *undoubtedly* cost us, the tax payers! It has to be *perfect* , or we have NO chance ever implementing this webservice
(Which would/will, btw, help our country a lot, adding at least 0.5 billions of USD annually into the state fund + probably even much more on taxes collected! )
---

Yes, I am pretty familiar with web development (13 years). Yet, I only was suspecting (feeling) this, but NOT logically/consciously KNOW *this*.

And I would never suspect/expect an error in the WSDL given by the government in the first place!
---


> however PHP is behaving correctly.
Are You *absolutely* sure about all this?

Then please: Tell (explain) this to the government!

Thank You soooooooooooo much :-)
 [2016-09-09 13:20 UTC] filip dot rydlo at gmail dot com
I would like to apologize to my government.

"millions of dollars" was of course clearly an *overstatement* from me.

I believe it could have cost several tens of thousands dollars, maybe up to one houndred thousand USD.  And mainly just because of the expensive infrastructure (a powerful dedicated server for the EET webservice is definitely needed. It will need to consume lots of data daily).
 [2016-09-09 14:06 UTC] requinix@php.net
-Status: Feedback +Status: Not a bug
 [2016-09-09 14:06 UTC] requinix@php.net
>> however PHP is behaving correctly.
>Are You *absolutely* sure about all this?
As I said, I welcome any evidence or documentation or such indicating the opposite, but I'm quite sure I'm right.

Are *you* sure that you have the correct WSDL URL? Try using /v3/?wsdl in your code instead - I bet it will work.
 [2016-09-09 14:22 UTC] filip dot rydlo at gmail dot com
Unfortunatelly: Yes, I am.

I have common sense. So, sadly, this simple fix was, of course, the *first* thing I have tried!

Try the fixed link in a web browser for yourself. The original link does.
It does NOT work as of today: 2016-09-09T16:20:00+0200 :

https://pg.eet.cz/eet/services/EETServiceSOAP/v3/?wsdl
 [2016-09-09 14:26 UTC] requinix@php.net
The original URL has never worked for me, so I don't know.

An alternative is to download and use the WSDLs locally. Any relative schemaLocation should continue to work without adjustment.
 [2016-09-09 15:48 UTC] filip dot rydlo at gmail dot com
Thank You, Requinix!

I will try that.

Of course with the
$options= array(... , 'location' => 'https://pg.eet.cz/eet/services/EETServiceSOAP/v3/');  //trailing slash
 [2016-09-09 18:35 UTC] filip dot rydlo at gmail dot com
This was a nightmare! OK. The local alternative (workaround) works fine. Thanx again!

But if they ever change the WSDL... well, then it will be REAL fuuuuuuuun! :-)))
 [2016-09-20 13:39 UTC] dzuelke at gmail dot come
The WSDL is located at the URL `https://pg.eet.cz/eet/services/EETServiceSOAP/v3?wsdl`.

It references an XML Schema file at `EETXMLSchema.xsd`, which is a relative location, so it's looked for relative to the containing document, at `https://pg.eet.cz/eet/services/EETServiceSOAP/EETXMLSchema.xsd`.

The correct location is `https://pg.eet.cz/eet/services/EETServiceSOAP/v3/EETXMLSchema.xsd`, but that's not PHP's problem. You should contact the owner of the service and ask them to fix the issue. Not only PHP, but all other clients that adhere to the spec will be unable to load this file, so it's in their interest to get it resolved.

Failing that, you can

1. use an XML catalog entry on your local system to re-define where `EETXMLSchema.xsd` is located;
2. load the WSDL file from the origin URL, cache it locally, and rewrite the `schemaLocation` to contain a full relative path (`/eet/services/EETServiceSOAP/v3/EETXMLSchema.xsd`) or even an absolute URL. Then load that local WSDL.

You really want to do option 2 in production anyway, because otherwise, your SoapClient instantiation will fetch the remote WSDL file on each instantiation, which slows down your app, and may break things even if you don't make a SOAP call if the endpoint is down.
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Wed Oct 20 13:03:32 2021 UTC