Bug in HTTP stream context causes problems in SoapClient/get_sdl()
| From: | Giovanni Giacobbi | Date: | Sun, 25 Jan 2009 21:43:52 +0000 |
| Subject: | Bug in HTTP stream context causes problems in SoapClient/get_sdl() | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-42834@lists.php.net to get a copy of this message | ||
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