Bug #81487 [NEW]: feof() should return true after reading last chunk for HTTP requests
| From: | public+php dot net at bastelstu dot be | Date: | Wed, 29 Sep 2021 08:36:23 +0000 |
| Subject: | Bug #81487 [NEW]: feof() should return true after reading last chunk for HTTP requests | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-236908@lists.php.net to get a copy of this message | ||
From: public+php dot net at bastelstu dot be
Operating system: Ubuntu 20.04 + Docker
PHP version: 8.0.11
Package: HTTP related
Bug Type: Bug
Bug description:feof() should return true after reading last chunk for HTTP requests
Description:
------------
When performing HTTP requests using
fopen(), feof() will not return
true until the server closes the connection, even if the full body has
already been received.
According to RFC 7230#6.6
(https://httpwg.org/specs/rfc7230.html#persistent.tear-down):
> A client that sends a "close" connection option MUST NOT send further
requests
> on that connection (after the one containing "close") and MUST close
the
> connection after reading the final response message corresponding to
this request.
PHP should detect that the full response message has been read and close
the socket.
---------------------
In my real world use case, I am using Guzzles StreamHandler
(https://github.com/guzzle/guzzle/blob/master/src/Handler/StreamHandler.php)
to perform HTTP requests, reading Open Graph metadata.
In one case I was apparently hitting a NetScaler load balancer
(https://www.nextthing.org/archives/2005/08/07/fun-with-http-headers#comment-24970).
These appear to ignore any Connection: close headers within the
request and keep the connection open (for minutes). This is in violation
of section RFC7230#6.6:
> A server that receives a "close" connection option MUST initiate a
close of
> the connection (see below) after it sends the final response to the
request
> that contained "close". The server SHOULD send a "close" connection
option
> in its final response on that connection. The server MUST NOT process
any
> further requests received on that connection.
*Nonetheless* PHP should also honor its side of RFC7230 and also
actually close the connection after receiving the response.
cURL on the command line and HTTPie both will close the connection on
their own.
Test script:
---------------
<?php
// Reproducer server in C:
// https://gist.github.com/TimWolla/0a94abd5c3a9e4c75f317910ac56fa80
$fd = fopen("http://172.17.0.1:8080",
"r");
while (!feof($fd)) {
var_dump(fread($fd, 2));
}
Expected result:
----------------
I expected the while loop to terminate after reading the 9 within
the response, like cURL does:
$ curl -v 'localhost:8080'
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 Ok
< Connection: keep-alive
< Transfer-Encoding: chunked
<
* Connection #0 to host localhost left intact
0123456789
Actual result:
--------------
The loop / script did not terminate until I terminated the HTTP server,
thus implicitly closing the socket:
$ php test.php
string(2) "01"
string(2) "23"
string(2) "45"
string(2) "67"
string(2) "89"
*hangs at this point*
--
Edit bug report at https://bugs.php.net/bug.php?id=81487&edit=1
--
Fix committed: https://bugs.php.net/fix.php?id=81487&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=81487&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=81487&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=81487&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=81487&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=81487&r=support
Expected behavior: https://bugs.php.net/fix.php?id=81487&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=81487&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=81487&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=81487&r=globals
PHP version support discontinued: https://bugs.php.net/fix.php?id=81487&r=phptooold
Daylight Savings: https://bugs.php.net/fix.php?id=81487&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=81487&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=81487&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=81487&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=81487&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=81487&r=mysqlcfg