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
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
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 01:01:30 2024 UTC