php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #80970 Default protocol_version in http resource context changed to HTTP 1.1 in PHP 8
Submitted: 2021-04-19 13:46 UTC Modified: 2021-04-19 14:33 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: zdenek dot crha at ui dot com Assigned:
Status: Open Package: HTTP related
PHP Version: 8.0.3 OS: GNU/Linux Debian Bullseye
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: zdenek dot crha at ui dot com
New email:
PHP Version: OS:

 

 [2021-04-19 13:46 UTC] zdenek dot crha at ui dot com
Description:
------------
## Overview

The documentation at https://www.php.net/manual/en/context.http.php states that the default `protocol_version` is HTTP 1.0. This does not seem to be true for PHP 8.0 anymore.

The changed default can be considered breaking change in some applications.

## Package versions

PHP 7.4.16 (cli) (built: Mar  5 2021 08:39:16) ( NTS )
PHP 8.0.3 (cli) (built: Mar  5 2021 08:37:58) ( NTS )

## Description

We have a code that interleaves reading data from HTTP endpoint and its processing. We use `stream_select()` to read partial response, do processing and loop until connection is closed. Basically long-poll/SSE client.

See extracted and minimized version in attachement.

The code worked fine in all PHP 7.4 versions but it started failing when we started migration to PHP 8.0.

* the expected result is recored from PHP 7.4.16
* the actual result is recored from PHP 8.0.3

The root cause of the crash/failure seems to originate from changed default value of `protocol_version` field used when creating http stream resource.

The PHP 7.4 is setting the `protocol_version` to "1.0" while the PHP 8.0 is setting it to "1.1".

Different protocol version seems result into different processing and failure to call `stream_select()` method on the resource due to cast issues

I have checked the documentation at https://www.php.net/manual/en/context.http.php and the page still says that the default protocol version is "1.0". I have tried to find any information about the change in PHP 8.0 changelog but failed.

I think that either of following would resolve the issue:

* reverted default protocol_version back to HTTP 1.0
* fix stream_select() or related code to handle HTTP 1.1 resources
* document the change and mark it as breaking in PHP 8.0 changelog

Test script:
---------------
#!/usr/bin/env php
<?php

$context = stream_context_create(['http' => [ 'method' => 'GET' ]]);
if ($stream  = fopen($argv[1] ?? 'http://www.php.net', 'r', false, $context)) {
    $read   = [$stream];
    $ignore = [];

    do {
        $count = stream_select($read, $ignore, $ignore, 5, 0);
        if (is_int($count) && $count > 0 && false !== ($text = fgets($stream))) {
            printf("0x%s\n", bin2hex($text));
        } else {
            exit(1);
        }
    } while (true);
}


Expected result:
----------------
0x3c21444f43545950452068746d6c3e0a                                                                                                                            
0x3c68746d6c20786d6c6e733d22687474703a2f2f7777772e77332e6f72672f313939392f7868746d6c22206c616e673d22656e223e0a                                                0x3c686561643e0a                                                                                                                                              
0x0a                                                 
.... snip many lines ....
0x0a
0x3c2f626f64793e0a
0x3c2f68746d6c3e0a


Actual result:
--------------
PHP Warning:  stream_select(): Cannot cast a filtered stream on this system in /home/bin/http-poll-client on line 12
PHP Stack trace:
PHP   1. {main}() /home/bin/http-poll-client:0
PHP   2. stream_select($read = [0 => resource(6) of type (stream)], $write = [], $except = [], $seconds = 5, $microseconds = 0) /home/bin/http-poll-client:12
PHP Fatal error:  Uncaught ValueError: No stream arrays were passed in /home/bin/http-poll-client:12
Stack trace:
#0 /home/bin/http-poll-client(12): stream_select()
#1 {main}
  thrown in /home/bin/http-poll-client on line 12

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-04-19 14:33 UTC] cmb@php.net
The actual problem is that the server responds with
Transfer-Encoding: chunked for HTTP/1.1 requests, and the
dechunking is implemented via a filter.
 [2021-04-19 14:34 UTC] rowan dot collins at gmail dot com
Just to note that the change is documented as a breaking change in the 8.0 migration guide: https://www.php.net/manual/en/migration80.incompatible.php

You are quite right that the other page needs updating.

Meanwhile, I can reproduce the error with the below, and it does seem to be protocol version related: with 'protocol_version'=>'1.0', it works on both 7.4 and 8.0; with 'protocol_version'=>'1.1' it break on both.

Sending some manual requests to the server, I can't see an obvious difference in response between protocol versions, so maybe there is something in PHP itself that is handling the connection differently when set to 1.1?
 [2021-04-19 14:37 UTC] rowan dot collins at gmail dot com
Ah, Chunked Encoding would certainly explain this, yes.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 06:01:30 2024 UTC