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 on PHP 8
Status: Verified
Type: Bug
Package: Streams related
Operating System: any
-PHP Version: 8.0.3
+PHP Version: 7.4
Block user comment: N
Private report: N
New Comment:
First, this is not a regression in PHP 8.0, but rather a general
issue with HTTP/1.1. It seems to me the problem is that the
server does *not* close the connection right away after having
sent the response under HTTP/1.1, what appears to be legit
behavior. After having received the full response, our HTTP stream
implementation still tries to select(2) the sole readfd, but the
server won't send more data, so the timeout occurs.
FWIW, if I add a Connection:keep-alive header to the context
options, I can reproduce the behavior of the server locally.
Previous Comments:
------------------------------------------------------------------------
[2021-04-07 20:43:12] gilperon at gmail dot com
danack@php.net Respectfully, setting manually the protocol to 1.0 is more like a hack to me than
anything else. Devs 99% of the time, don't have control over the API response, they cannot fix
server's misconfiguration only so their code works. Devs expect file_get_contents to simply
work. Curl works just fine with this URL while file_get_contents is buggy. I don't expect Curl
to have lots of hacks and I am pretty sure Curl has a nice workaround about server not closing
connection - and so PHP should do. No hacks, I agree with you, hacks are terrible and probably will
break something in the future.
------------------------------------------------------------------------
[2021-04-07 20:11:49] danack@php.net
Setting the protocol back to 1.0 with the protocol version option appears to make it work on 8.
I'll need to actually inspect the packets to have a deeper look.
> But I am pretty sure it will start bothering many other devs as they
> update their PHP to 8.x and start seeing their code breaking.
To set your expectation, if this is a bug on the remote server, then it's unlikely we would
write a hack around it. People can either use a workaround in their code, stay on PHP7, or ask the
person who owns that site to fix it. It's not feasible to put work arounds in php core for all
buggy servers out there.
<?php
$context = stream_context_create(array(
"http" => array(
"protocol_version" => "1.0"
)
));
$response = file_get_contents("http://ws.correios.com.br/calculador/CalcPrecoPrazo.aspx?nCdEmpresa=&sDsSenha=&sCepOrigem=11661690&sCepDestino=88070-480&nVlPeso=1&nCdFormato=1&nVlComprimento=25&nVlAltura=3&nVlLargura=25&sCdMaoPropria=N&nVlValorDeclarado=0&sCdAvisoRecebimento=N&nCdServico=04014&nVlDiametro=0&StrRetorno=xml",
0, $context);
echo "response length is " . strlen($response) . "\n";
------------------------------------------------------------------------
[2021-04-07 17:21:45] gilperon at gmail dot com
I just want to point that Correios (http://correios.com.br/), whose API I am using and which is the
one that makes file_get_contents dont work as expected, is the largest shipping
organization in Brazil (96% marketshare), and it's owned by the brazilian goverment. I am
pretty sure many many devs use this API with PHP and I am probably one of the few to face this
problem because, probably, many devs are still using older versions of PHP here in brazil. But I am
pretty sure it will start bothering many other devs as they update their PHP to 8.x and start seeing
their code breaking. Just a side note in case you think I am using a "special URL" only
created to make this problem happen (the URL I provided you is the official goverment end point of
their webhook).
------------------------------------------------------------------------
[2021-04-07 16:59:05] danack@php.net
Oh, the difference is PHP 7 set HTTP/1.0, PHP 8 does HTTP/1.1
"GET
/calculador/CalcPrecoPrazo.aspx?nCdEmpresa=&sDsSenha=&sCepOrigem=11661690&sCepDestino=88070-480&nVlPeso=1&nCdFormato=1&nVlComprimento=25&nVlAltura=3&nVlLargura=25&sCdMaoPropria=N&nVlValorDeclarado=0&sCdAvisoRecebimento=N&nCdServico=04014&nVlDiametro=0&StrRetorno=xml
HTTP/1.0\r\nHost: ws.correios.com.br\r\nConnection: close\r\n\r\n"
"GET
/calculador/CalcPrecoPrazo.aspx?nCdEmpresa=&sDsSenha=&sCepOrigem=11661690&sCepDestino=88070-480&nVlPeso=1&nCdFormato=1&nVlComprimento=25&nVlAltura=3&nVlLargura=25&sCdMaoPropria=N&nVlValorDeclarado=0&sCdAvisoRecebimento=N&nCdServico=04014&nVlDiametro=0&StrRetorno=xml
HTTP/1.1\r\nHost: ws.correios.com.br\r\nConnection: close\r\n\r\n"
------------------------------------------------------------------------
[2021-04-07 16:57:04] nikic@php.net
PHP 8 uses HTTP 1.1 instead of HTTP 1.0 by default, maybe that's related?
------------------------------------------------------------------------
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