Skip to content

HTTP client doesn't handle responses with Transfer-Encoding: chunked #104

Open
@maypaw

Description

@maypaw

In the process of working on #82 (E2E tests) with @reimic we found an issue with the way how the HTTP client handles chunked streams.

Currently, the response is written with the chunk markers, as if they were normal characters. This corrupts the wp-cli.phar. Handling Transfer-Encoding: chunked is expected behaviour of HTTP/1.1 protocol.

At the moment we have two ideas how to handle this issue:

  1. Change the used HTTP protocol version to HTTP/1.0, which by default doesn't support chunks.
    Currently the function stream_http_prepare_request_bytes in async_http_streams.php prepares a request in 1.1:
$request = <<<REQUEST
GET $path HTTP/1.1 // We could change this to: GET $path HTTP/1.0
[...]
REQUEST;

We've tested this approach and it works. The downside to this would be probable performance loss, since HTTP/1.1 is supposedly more efficient. Yet neither I nor @reimic are capable of assessing the influence of such change.

  1. Alternatively, the streams could be filtered with the PHP dechunk filter when performing read or write operations. We have also tested that this can work. Yet this is somewhat problematic:
    We tried appending the filter after the stream creation, in function streams_http_open_nonblocking in async_http_streams.php and several other places. Unfortunately, due to usage of @stream_select in continuous reading and writing the response, appending stream filter while performing those operations is impossible (reference: PHP8: Uncaught ValueError: No stream arrays wered pased in StreamSelectLoop:: reactphp/event-loop#220).
    The first place, where it worked as expected, was at the very last possible moment, i.e. while copying the already closed stream in run method of WriteFileStepRunner.php.
public function run(
   	$input,
   	$progress = null
   ) { 
        [...]
   	$fp2 = fopen( $path, 'w' );
        [...]
        stream_filter_append($fp2,"dechunk",STREAM_FILTER_WRITE); // dechunking the stream
   	stream_copy_to_stream( $this->getResource( $input->data ), $fp2 );
   	fclose( $fp2 );
}

This doesn't seem like the right place to do this though, as dechunking should probably be done when handling the response in the client.

@adamziel what do you think?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions