Description
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:
- Change the used HTTP protocol version to HTTP/1.0, which by default doesn't support chunks.
Currently the functionstream_http_prepare_request_bytes
inasync_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.
- 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 functionstreams_http_open_nonblocking
inasync_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 inrun
method ofWriteFileStepRunner.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?