Bug #80931 [Ver]: file_get_contents() hangs with HTTP/1.1 if server doesn't close connection

From: Date: Wed, 14 Apr 2021 09:34:12 +0000
Subject: Bug #80931 [Ver]: file_get_contents() hangs with HTTP/1.1 if server doesn't close connection
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-233421@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=80931&edit=1

 ID:                 80931
 Updated by:         twosee@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:

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>


Previous Comments:
------------------------------------------------------------------------
[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/");'

------------------------------------------------------------------------
[2021-04-08 18:34:07] gilperon at gmail dot com

I think you guys could check how CURL does it, because it handles this "buggy coreios
server" well; it does not hang.

Also, could you please take a look at https://stackoverflow.com/questions/34864179/prevent-php-http-wrapper-from-waiting-for-close-of-persistent-connection
? This looks a similar problem from 5 years ago that I just found out talking with people on discord
server.

------------------------------------------------------------------------


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


Thread (35 messages)

« previous php.bugs (#233421) next »