Greetings,
I recently upgraded to the latest PHP 5.3 snapshot and I found the following
SoapClient bug:
<?php
ini_set("soap.wsdl_cache_enabled", 0);
new SoapClient("http://localhost/ws/catalog?wsdl");
?>
Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL:
Couldn't load from 'http://localhost/ws/catalog?wsdl' : Start tag expected, '<'
not found
The problem turned out to be an invalid interpretation of the HTTP/1.1 protocol
with "Transfer-Encoding: chunked" by the HTTP stream context, which caused
get_sdl() to parse a WSDL including the chunk tags (hex numbers).
Chunked encoding is used by Apache 2.0 when "Content-Length" is unavailable,
the data content being sent is large enough, and the protocol is HTTP/1.1.
I initially tried using readfile() but I didn't get the same problem.
Eventually I could finally reproduce the bug with the following script:
<?php
$opts = array('http' => array('method' => "GET", 'header' => "Accept-language:
en\r\nConnection: close\r\n"));
$context = stream_context_create($opts);
stream_context_set_option($context, "http", "protocol_version", 1.1);
fpassthru(fopen('http://localhost/ws/catalog?wsdl', 'r', false, $context));
?>
I can notice various problems here:
1) All the chunk tags are left in place and the extra newlines are not
stripped, leading to corrupted data.
2) Without the "Connection: close" header the stream blocks until http timeout.
It should instead detect the chunk with 0 bytes and return from the fpassthru().
In the meanwhile, the following patch is a workaround for the problem I had: it
restores the default HTTP/1.0.
Side note: Shouldn't the last smart_str_appendl() call also contain an EOL?
Side note #2: Is there any way to avoid repeating the same string twice? It's
very common in the soap extension and I think it's really error prone.
Side note #3: Is it possible to create a test for this bug? Like a raw HTTP/1.1
response stored in a text file with chunk encoding and a script that loads that
data...?
--- ext/soap/php_sdl.c.orig 2008-12-31 12:37:12.000000000 +0100
+++ ext/soap/php_sdl.c 2009-01-25 22:09:14.000000000 +0100
@@ -3192,14 +3192,16 @@
basic_authentication(this_ptr, &headers TSRMLS_CC);
/* Use HTTP/1.1 with "Connection: close" by default */
+#if 0
if (php_stream_context_get_option(context, "http", "protocol_version",
&tmp) == FAILURE) {
- zval *http_version;
+ zval *http_version;
MAKE_STD_ZVAL(http_version);
ZVAL_DOUBLE(http_version, 1.1);
php_stream_context_set_option(context, "http",
"protocol_version", http_version);
zval_ptr_dtor(&http_version);
smart_str_appendl(&headers, "Connection: close",
sizeof("Connection: close")-1);
}
+#endif
if (headers.len > 0) {
zval *str_headers;
Regards
--
Giovanni Giacobbi
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php