19 May 2012

Gentoo - PHP 5.3.13 - SoapFault: Start tag expected, '<' not found

Surprisingly I've found that PHP's SoapClient doesn't work properly on my laptop with Gentoo Linux.

Sample code:
$client = new SoapClient("http://localhost/wsdl.xml");


Exception text:
SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost/wsdl.xml' : Start tag expected, '<' not found


The issue is reproducible for HTTP and HTTPS, for local and remote websites. Also you can download the WSDL file and provide it to SoapClient as a string and in this case it works. Something wrong in getting WSDL via HTTP(S).
I googled and researched it a bit and found following:
  • I'm not first who found this issue :-)
  • There is bug in bugzilla: https://bugs.php.net/bug.php?id=47021
  • The issue is linked to DNS stack; code starts to work if you replace DNS name by IP address  (worked for me), but that obviously won't work for name based virtual hosts
  • There is also information that issue appears for chunked encoding of HTTP response. SoapClient can't deal with it. However there is working workaround (I didn't test) by using HTTP 1.0 via stream contexts (code is given in comments of bug page linked above)
  • Another workaround linked to HTTP 1.0 is to use proxy - by default proxies do not work with HTTP 1.1 and that fixes issue:  http://hoschie.org/2012/02/contao-soapfault-start-tag-expected/
  • In some cases it might be fixed by disabling "curlwrapper" in PHP's compilation options. It worked for me, but people complain that it doesn't work for everybody.
In general case you can disable curlwrapper by adding following parameter to configure script:
./configure --without-curlwrapper

On Gentoo Linux you can do it by disabling "curlwrapper" USE flag for ebuild dev-lang/php
It can be done by putting following line to file /etc/portage/package.use 
dev-lang/php -curlwrapper

Full list of flags which worked for me:
dev-lang/php-5.3.13  USE="apache2 berkdb bzip2 cli crypt ctype curl exif fileinfo filter gd gdbm hash iconv inifile json ldap mysql mysqli nls pdo phar pic posix readline session simplexml soap sockets spell sqlite ssl sysvipc threads tidy tokenizer truetype unicode xml xmlreader xmlrpc xmlwriter xsl zip zlib -bcmath -calendar -cdb -cgi -cjk -curlwrappers -debug -doc -embed -enchant -firebird -flatfile -fpm -frontbase -ftp -gmp -imap -intl -iodbc -ipv6 -kerberos -kolab -ldap-sasl -libedit -mhash -mssql -mysqlnd -oci8-instant-client -odbc -pcntl -postgres -qdbm -recode -sharedmem -snmp -sqlite3 -suhosin -sybase-ct -wddx -xpm"

8 comments:

  1. Worked for me, but my question is - is there anyway to help soap get past this on a local level without disabling the curlwrapper globally?

    Cheers

    ReplyDelete
    Replies
    1. Hi,

      Sorry for late reply.
      I didn't find solution for that. As far as I remember it was on level of PHP extension, I don't think it's fixable locally.

      -- Andrey.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. In our case the problem was caused by Akamai, which in this instance acts as a geographical reverse proxy for any request.

    The client was making a SOAP call to the server, then the server-app was making its own call to retrieve the WSDL, using a PHP SoapServer call and this is where things failed, exactly as described in your blog.
    Akamai introduced chunked encoding, the requests header from Akamai to the origin server contained:
    [TE] => chunked;q=1.0
    [Connection] => TE, keep-alive

    To overcome the issue we simply defined the site's domain name in the /etc/hosts table in order to use the internal IP when the server itself makes calls to the site to get the WSDL, rather than doing a long round-trip via Akamai.
    Avoiding Akamai resolved the issue.

    However, if the initial SOAP call is made by a PHP Soap client retrieving the WSDL, it would face the same issues...

    ReplyDelete
  4. It's interesting, but today during Magento module development I've found that Soap fails on Fedora 17 if I enable XDebug. It fails to get WSDL. It also may be linked issue. I'll try to investigate later.

    ReplyDelete
  5. Hi there,

    I have similar issue but I am on IIS windows. so I am unable to find curlwrapper.
    My PHP version 5.4 is working fine but does not work fine with PHP 5.5 and gives the same error message.

    Please suggest?

    ReplyDelete
    Replies
    1. I know it isn't easy, but did you try to reconfigure & rebuild PHP from sources ?

      Delete
    2. We've found another SoapClient issue today:
      SoapClient was constantly failing on server with PHP 5.5 until we disabled keep_alive for it.

      Changes in our code:

      - $client = new SoapClient($wsdl, array('trace' => $trace));
      + $client = new SoapClient($wsdl, array('trace' => $trace, 'keep_alive' => false));

      Delete

Profile