Edit report at https://bugs.php.net/bug.php?id=80931&edit=1
ID: 80931
Updated by: cmb@php.net
Reported by: gilperon at gmail dot com
Summary: file_get_contents() hangs with HTTP/1.1 if server
doesn't close connection
Status: Verified
Type: Bug
Package: Streams related
Operating System: any
PHP Version: 7.4
Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
On a quick look, it seems to me that your patch would not work for
Transfer-encoding:chunked since it uses file_size which is 0 in
that case. A chunked body ends with an empty chunk (0\r\n).
The idea of using filters to solve the issue (suggested by Rowan
Tommins) allows to cater to that (regardless of auto_decode), at
the cost of a slight inefficiency (due to the need to copy the
buckets).
Previous Comments:
------------------------------------------------------------------------
[2021-04-14 09:34:12] twosee@php.net
Nice patch, I am not familiar with the filter part... it seems that my patch[1] is too crude...
[1] <https://github.com/php/php-src/compare/master...twose:bug80931>
------------------------------------------------------------------------
[2021-04-14 08:27:47] cmb@php.net
> In my opinion, this is a PHP design problem for all versions.
I agree. I'm working on a possible fix[1].
[1] <https://github.com/php/php-src/compare/master...cmb69:cmb/80931>
------------------------------------------------------------------------
[2021-04-14 03:45:48] twosee@php.net
In my opinion, this is a PHP design problem for all versions.
file_get_content("http://*") (php http stream
wrapper) always depends on the behavior of the server. It always expects recv to return 0 and uses
this to detect the end of the response.
But, if the peer does not close the connection, it will wait for data forever.
In this case, even if we set "Connection: close" when the protocol version is 1.1, the
server still treats it as a persistent connection, although the server also has implementation
problems, it did expose the problem of PHP.
So we can reproduce this problem on almost all websites:
<?php
$context = stream_context_create(['http' => ['protocol_version' => 1.1,
'header' => ['Connection: keep-alive']]]);
echo file_get_contents("http://www.baidu.com",
0, $context); // largest search engine in China
// hang...
------------------------------------------------------------------------
[2021-04-09 14:25:24] kelunik@php.net
https://gist.github.com/kelunik/c82ce751c1c203806b10ef7326f3e56a
fixes it for chunked encoding, but still fails with a content-length or if auto_decode = false.
------------------------------------------------------------------------
[2021-04-09 13:11:04] kelunik@php.net
Simple reproduce script:
php -r '$server = stream_socket_server("tcp://127.0.0.1:8080"); while ($client =
stream_socket_accept($server)) { fwrite($client, "HTTP/1.1 200 OK\r\ncontent-length:
0\r\n\r\n"); }'
php -r 'file_get_contents("http://127.0.0.1:8080/");'
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=80931
--
Edit this bug report at https://bugs.php.net/bug.php?id=80931&edit=1