From aba3d174a07dad3f903148e51a6d5ce90c53b97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Fri, 26 Jan 2018 19:05:01 +0100 Subject: [PATCH 01/16] Replace Guzzle with RingCentral --- composer.json | 4 ++-- src/Request.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index fe0e2f2..8619309 100644 --- a/composer.json +++ b/composer.json @@ -5,12 +5,12 @@ "license": "MIT", "require": { "php": ">=5.4.0", - "guzzlehttp/psr7": "^1.0", + "evenement/evenement": "^3.0 || ^2.0", "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3", "react/socket": "^1.0 || ^0.8.4", "react/stream": "^1.0 || ^0.7.1", "react/promise": "~2.2", - "evenement/evenement": "^3.0 || ^2.0" + "ringcentral/psr7": "^1.2" }, "require-dev": { "phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35" diff --git a/src/Request.php b/src/Request.php index 8a23b94..c1aa1bf 100644 --- a/src/Request.php +++ b/src/Request.php @@ -3,11 +3,11 @@ namespace React\HttpClient; use Evenement\EventEmitterTrait; -use GuzzleHttp\Psr7 as gPsr; use React\Promise; +use React\Socket\ConnectionInterface; use React\Socket\ConnectorInterface; use React\Stream\WritableStreamInterface; -use React\Socket\ConnectionInterface; +use RingCentral\Psr7 as gPsr; /** * @event response From 55f22bb7cb0659f068cda63589cbd03234900d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Thu, 8 Feb 2018 13:50:25 +0100 Subject: [PATCH 02/16] Test against PHP 7.2 --- .travis.yml | 7 ++++--- tests/FunctionalIntegrationTest.php | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 05680f2..07baf1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ php: - 5.6 - 7.0 - 7.1 + - 7.2 - nightly # ignore errors, see below - hhvm # ignore errors, see below @@ -17,8 +18,8 @@ matrix: - php: nightly - php: hhvm -before_script: - - composer install - +install: + - composer install --no-interaction + script: - vendor/bin/phpunit --coverage-text diff --git a/tests/FunctionalIntegrationTest.php b/tests/FunctionalIntegrationTest.php index cfa6800..1ed2228 100644 --- a/tests/FunctionalIntegrationTest.php +++ b/tests/FunctionalIntegrationTest.php @@ -15,6 +15,7 @@ public function testRequestToLocalhostEmitsSingleRemoteConnection() $loop = Factory::create(); $server = new Server(0, $loop); + $server->on('connection', $this->expectCallableOnce()); $server->on('connection', function (ConnectionInterface $conn) use ($server) { $conn->end("HTTP/1.1 200 OK\r\n\r\nOk"); $server->close(); From ce9b58b60201991695d0c216ac534f5c077a03fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Fri, 26 Jan 2018 12:18:52 +0100 Subject: [PATCH 03/16] Improve backwards compatibility with Promise v1 --- composer.json | 2 +- src/Request.php | 2 +- tests/RequestTest.php | 19 ------------------- 3 files changed, 2 insertions(+), 21 deletions(-) diff --git a/composer.json b/composer.json index 8619309..c98729d 100644 --- a/composer.json +++ b/composer.json @@ -7,9 +7,9 @@ "php": ">=5.4.0", "evenement/evenement": "^3.0 || ^2.0", "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3", + "react/promise": "^2.1 || ^1.2.1", "react/socket": "^1.0 || ^0.8.4", "react/stream": "^1.0 || ^0.7.1", - "react/promise": "~2.2", "ringcentral/psr7": "^1.2" }, "require-dev": { diff --git a/src/Request.php b/src/Request.php index c1aa1bf..ac42b5f 100644 --- a/src/Request.php +++ b/src/Request.php @@ -56,7 +56,7 @@ private function writeHead() $pendingWrites = &$this->pendingWrites; $promise = $this->connect(); - $promise->done( + $promise->then( function (ConnectionInterface $stream) use ($requestData, &$streamRef, &$stateRef, &$pendingWrites) { $streamRef = $stream; diff --git a/tests/RequestTest.php b/tests/RequestTest.php index 1d45c9b..c55c53b 100644 --- a/tests/RequestTest.php +++ b/tests/RequestTest.php @@ -272,25 +272,6 @@ public function requestShouldEmitErrorIfUrlHasNoScheme() $request->end(); } - /** - * @test - * @expectedException Exception - * @expectedExceptionMessage something failed - */ - public function requestDoesNotHideErrors() - { - $requestData = new RequestData('GET', 'http://www.example.com'); - $request = new Request($this->connector, $requestData); - - $this->rejectedConnectionMock(); - - $request->on('error', function () { - throw new \Exception('something failed'); - }); - - $request->end(); - } - /** @test */ public function postRequestShouldSendAPostRequest() { From 1ebab24f5c84593966955d31af7a30055cd370d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sun, 19 Mar 2017 19:12:20 +0100 Subject: [PATCH 04/16] Compatibility with legacy PHP 5.3 --- .travis.yml | 4 + README.md | 2 +- composer.json | 4 +- src/ChunkedStreamDecoder.php | 22 ++-- src/Client.php | 2 +- src/Request.php | 30 +++--- src/RequestData.php | 2 +- src/Response.php | 5 +- tests/DecodeChunkedStreamTest.php | 164 +++++++++++++++--------------- tests/RequestDataTest.php | 2 +- tests/RequestTest.php | 7 +- tests/ResponseTest.php | 16 +-- 12 files changed, 130 insertions(+), 130 deletions(-) diff --git a/.travis.yml b/.travis.yml index 07baf1e..46a0486 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: php php: +# - 5.3 # requires old distro - 5.4 - 5.5 - 5.6 @@ -14,6 +15,9 @@ php: dist: trusty matrix: + include: + - php: 5.3 + dist: precise allow_failures: - php: nightly - php: hhvm diff --git a/README.md b/README.md index 2c98d6c..c8494f6 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ $ composer require react/http-client:^0.5.7 See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. This project aims to run on any platform and thus does not require any PHP -extensions and supports running on legacy PHP 5.4 through current PHP 7+ and +extensions and supports running on legacy PHP 5.3 through current PHP 7+ and HHVM. It's *highly recommended to use PHP 7+* for this project. diff --git a/composer.json b/composer.json index c98729d..ecb19e5 100644 --- a/composer.json +++ b/composer.json @@ -4,8 +4,8 @@ "keywords": ["http"], "license": "MIT", "require": { - "php": ">=5.4.0", - "evenement/evenement": "^3.0 || ^2.0", + "php": ">=5.3.0", + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3", "react/promise": "^2.1 || ^1.2.1", "react/socket": "^1.0 || ^0.8.4", diff --git a/src/ChunkedStreamDecoder.php b/src/ChunkedStreamDecoder.php index 703eee3..a96592e 100644 --- a/src/ChunkedStreamDecoder.php +++ b/src/ChunkedStreamDecoder.php @@ -2,7 +2,7 @@ namespace React\HttpClient; -use Evenement\EventEmitterTrait; +use Evenement\EventEmitter; use Exception; use React\Stream\ReadableStreamInterface; use React\Stream\Util; @@ -11,12 +11,10 @@ /** * @internal */ -class ChunkedStreamDecoder implements ReadableStreamInterface +class ChunkedStreamDecoder extends EventEmitter implements ReadableStreamInterface { const CRLF = "\r\n"; - use EventEmitterTrait; - /** * @var string */ @@ -55,9 +53,9 @@ public function __construct(ReadableStreamInterface $stream) $this->stream = $stream; $this->stream->on('data', array($this, 'handleData')); $this->stream->on('end', array($this, 'handleEnd')); - Util::forwardEvents($this->stream, $this, [ + Util::forwardEvents($this->stream, $this, array( 'error', - ]); + )); } /** @internal */ @@ -89,9 +87,9 @@ protected function iterateBuffer() if ($this->nextChunkIsLength) { $crlfPosition = strpos($this->buffer, static::CRLF); if ($crlfPosition === false && strlen($this->buffer) > 1024) { - $this->emit('error', [ + $this->emit('error', array( new Exception('Chunk length header longer then 1024 bytes'), - ]); + )); $this->close(); return false; } @@ -114,9 +112,9 @@ protected function iterateBuffer() } $this->nextChunkIsLength = false; if (dechex(hexdec($lengthChunk)) !== strtolower($lengthChunk)) { - $this->emit('error', [ + $this->emit('error', array( new Exception('Unable to validate "' . $lengthChunk . '" as chunk length header'), - ]); + )); $this->close(); return false; } @@ -200,9 +198,9 @@ public function handleEnd() $this->emit( 'error', - [ + array( new Exception('Stream ended with incomplete control code') - ] + ) ); $this->close(); } diff --git a/src/Client.php b/src/Client.php index fb8230b..fc14426 100644 --- a/src/Client.php +++ b/src/Client.php @@ -19,7 +19,7 @@ public function __construct(LoopInterface $loop, ConnectorInterface $connector = $this->connector = $connector; } - public function request($method, $url, array $headers = [], $protocolVersion = '1.0') + public function request($method, $url, array $headers = array(), $protocolVersion = '1.0') { $requestData = new RequestData($method, $url, $headers, $protocolVersion); diff --git a/src/Request.php b/src/Request.php index ac42b5f..ea4d50b 100644 --- a/src/Request.php +++ b/src/Request.php @@ -2,7 +2,7 @@ namespace React\HttpClient; -use Evenement\EventEmitterTrait; +use Evenement\EventEmitter; use React\Promise; use React\Socket\ConnectionInterface; use React\Socket\ConnectorInterface; @@ -15,10 +15,8 @@ * @event error * @event end */ -class Request implements WritableStreamInterface +class Request extends EventEmitter implements WritableStreamInterface { - use EventEmitterTrait; - const STATE_INIT = 0; const STATE_WRITING_HEAD = 1; const STATE_HEAD_WRITTEN = 2; @@ -54,17 +52,18 @@ private function writeHead() $streamRef = &$this->stream; $stateRef = &$this->state; $pendingWrites = &$this->pendingWrites; + $that = $this; $promise = $this->connect(); $promise->then( - function (ConnectionInterface $stream) use ($requestData, &$streamRef, &$stateRef, &$pendingWrites) { + function (ConnectionInterface $stream) use ($requestData, &$streamRef, &$stateRef, &$pendingWrites, $that) { $streamRef = $stream; - $stream->on('drain', array($this, 'handleDrain')); - $stream->on('data', array($this, 'handleData')); - $stream->on('end', array($this, 'handleEnd')); - $stream->on('error', array($this, 'handleError')); - $stream->on('close', array($this, 'handleClose')); + $stream->on('drain', array($that, 'handleDrain')); + $stream->on('data', array($that, 'handleData')); + $stream->on('end', array($that, 'handleEnd')); + $stream->on('error', array($that, 'handleError')); + $stream->on('close', array($that, 'handleClose')); $headers = (string) $requestData; @@ -77,7 +76,7 @@ function (ConnectionInterface $stream) use ($requestData, &$streamRef, &$stateRe $pendingWrites = ''; if ($more) { - $this->emit('drain'); + $that->emit('drain'); } } }, @@ -154,11 +153,10 @@ public function handleData($data) return; } - $response->on('close', function () { - $this->close(); - }); - $response->on('error', function (\Exception $error) { - $this->closeError(new \RuntimeException( + $response->on('close', array($this, 'close')); + $that = $this; + $response->on('error', function (\Exception $error) use ($that) { + $that->closeError(new \RuntimeException( "An error occured in the response", 0, $error diff --git a/src/RequestData.php b/src/RequestData.php index 7ec0e2a..1c7d5eb 100644 --- a/src/RequestData.php +++ b/src/RequestData.php @@ -9,7 +9,7 @@ class RequestData private $headers; private $protocolVersion; - public function __construct($method, $url, array $headers = [], $protocolVersion = '1.0') + public function __construct($method, $url, array $headers = array(), $protocolVersion = '1.0') { $this->method = $method; $this->url = $url; diff --git a/src/Response.php b/src/Response.php index 88605dd..5ed271f 100644 --- a/src/Response.php +++ b/src/Response.php @@ -12,9 +12,8 @@ * @event error * @event end */ -class Response extends EventEmitter implements ReadableStreamInterface +class Response extends EventEmitter implements ReadableStreamInterface { - private $stream; private $protocol; private $version; @@ -166,7 +165,7 @@ public function resume() $this->stream->resume(); } - public function pipe(WritableStreamInterface $dest, array $options = []) + public function pipe(WritableStreamInterface $dest, array $options = array()) { Util::pipe($this, $dest, $options); diff --git a/tests/DecodeChunkedStreamTest.php b/tests/DecodeChunkedStreamTest.php index 62aa84f..83e8858 100644 --- a/tests/DecodeChunkedStreamTest.php +++ b/tests/DecodeChunkedStreamTest.php @@ -10,81 +10,81 @@ class DecodeChunkedStreamTest extends TestCase { public function provideChunkedEncoding() { - return [ - 'data-set-1' => [ - ["4\r\nWiki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"], - ], - 'data-set-2' => [ - ["4\r\nWiki\r\n", "5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"], - ], - 'data-set-3' => [ - ["4\r\nWiki\r\n", "5\r\n", "pedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"], - ], - 'data-set-4' => [ - ["4\r\nWiki\r\n", "5\r\n", "pedia\r\ne\r\n in\r\n", "\r\nchunks.\r\n0\r\n\r\n"], - ], - 'data-set-5' => [ - ["4\r\n", "Wiki\r\n", "5\r\n", "pedia\r\ne\r\n in\r\n", "\r\nchunks.\r\n0\r\n\r\n"], - ], - 'data-set-6' => [ - ["4\r\n", "Wiki\r\n", "5\r\n", "pedia\r\ne; foo=[bar,beer,pool,cue,win,won]\r\n", " in\r\n", "\r\nchunks.\r\n0\r\n\r\n"], - ], - 'header-fields' => [ - ["4; foo=bar\r\n", "Wiki\r\n", "5\r\n", "pedia\r\ne\r\n", " in\r\n", "\r\nchunks.\r\n", "0\r\n\r\n"], - ], - 'character-for-charactrr' => [ + return array( + 'data-set-1' => array( + array("4\r\nWiki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"), + ), + 'data-set-2' => array( + array("4\r\nWiki\r\n", "5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"), + ), + 'data-set-3' => array( + array("4\r\nWiki\r\n", "5\r\n", "pedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"), + ), + 'data-set-4' => array( + array("4\r\nWiki\r\n", "5\r\n", "pedia\r\ne\r\n in\r\n", "\r\nchunks.\r\n0\r\n\r\n"), + ), + 'data-set-5' => array( + array("4\r\n", "Wiki\r\n", "5\r\n", "pedia\r\ne\r\n in\r\n", "\r\nchunks.\r\n0\r\n\r\n"), + ), + 'data-set-6' => array( + array("4\r\n", "Wiki\r\n", "5\r\n", "pedia\r\ne; foo=[bar,beer,pool,cue,win,won]\r\n", " in\r\n", "\r\nchunks.\r\n0\r\n\r\n"), + ), + 'header-fields' => array( + array("4; foo=bar\r\n", "Wiki\r\n", "5\r\n", "pedia\r\ne\r\n", " in\r\n", "\r\nchunks.\r\n", "0\r\n\r\n"), + ), + 'character-for-charactrr' => array( str_split("4\r\nWiki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"), - ], - 'extra-newline-in-wiki-character-for-chatacter' => [ + ), + 'extra-newline-in-wiki-character-for-chatacter' => array( str_split("6\r\nWi\r\nki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"), "Wi\r\nkipedia in\r\n\r\nchunks." - ], - 'extra-newline-in-wiki' => [ - ["6\r\nWi\r\n", "ki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"], + ), + 'extra-newline-in-wiki' => array( + array("6\r\nWi\r\n", "ki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"), "Wi\r\nkipedia in\r\n\r\nchunks." - ], - 'varnish-type-response-1' => [ - ["0017\r\nWikipedia in\r\n\r\nchunks.\r\n0\r\n\r\n"] - ], - 'varnish-type-response-2' => [ - ["000017\r\nWikipedia in\r\n\r\nchunks.\r\n0\r\n\r\n"] - ], - 'varnish-type-response-3' => [ - ["017\r\nWikipedia in\r\n\r\nchunks.\r\n0\r\n\r\n"] - ], - 'varnish-type-response-4' => [ - ["004\r\nWiki\r\n005\r\npedia\r\n00e\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"] - ], - 'varnish-type-response-5' => [ - ["000004\r\nWiki\r\n00005\r\npedia\r\n000e\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"] - ], - 'varnish-type-response-extra-line' => [ - ["006\r\nWi\r\nki\r\n005\r\npedia\r\n00e\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"], + ), + 'varnish-type-response-1' => array( + array("0017\r\nWikipedia in\r\n\r\nchunks.\r\n0\r\n\r\n") + ), + 'varnish-type-response-2' => array( + array("000017\r\nWikipedia in\r\n\r\nchunks.\r\n0\r\n\r\n") + ), + 'varnish-type-response-3' => array( + array("017\r\nWikipedia in\r\n\r\nchunks.\r\n0\r\n\r\n") + ), + 'varnish-type-response-4' => array( + array("004\r\nWiki\r\n005\r\npedia\r\n00e\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n") + ), + 'varnish-type-response-5' => array( + array("000004\r\nWiki\r\n00005\r\npedia\r\n000e\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n") + ), + 'varnish-type-response-extra-line' => array( + array("006\r\nWi\r\nki\r\n005\r\npedia\r\n00e\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"), "Wi\r\nkipedia in\r\n\r\nchunks." - ], - 'varnish-type-response-random' => [ - [str_repeat("0", rand(0, 10)), "4\r\nWiki\r\n", str_repeat("0", rand(0, 10)), "5\r\npedia\r\n", str_repeat("0", rand(0, 10)), "e\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"] - ], - 'end-chunk-zero-check-1' => [ - ["4\r\nWiki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n00\r\n\r\n"] - ], - 'end-chunk-zero-check-2' => [ - ["4\r\nWiki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n000\r\n\r\n"] - ], - 'end-chunk-zero-check-3' => [ - ["00004\r\nWiki\r\n005\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0000\r\n\r\n"] - ], - 'uppercase-chunk' => [ - ["4\r\nWiki\r\n5\r\npedia\r\nE\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"], - ], - 'extra-space-in-length-chunk' => [ - [" 04 \r\nWiki\r\n5\r\npedia\r\nE\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"], - ], - 'only-whitespace-is-final-chunk' => [ - [" \r\n\r\n"], + ), + 'varnish-type-response-random' => array( + array(str_repeat("0", rand(0, 10)), "4\r\nWiki\r\n", str_repeat("0", rand(0, 10)), "5\r\npedia\r\n", str_repeat("0", rand(0, 10)), "e\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n") + ), + 'end-chunk-zero-check-1' => array( + array("4\r\nWiki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n00\r\n\r\n") + ), + 'end-chunk-zero-check-2' => array( + array("4\r\nWiki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n000\r\n\r\n") + ), + 'end-chunk-zero-check-3' => array( + array("00004\r\nWiki\r\n005\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0000\r\n\r\n") + ), + 'uppercase-chunk' => array( + array("4\r\nWiki\r\n5\r\npedia\r\nE\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"), + ), + 'extra-space-in-length-chunk' => array( + array(" 04 \r\nWiki\r\n5\r\npedia\r\nE\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"), + ), + 'only-whitespace-is-final-chunk' => array( + array(" \r\n\r\n"), "" - ] - ]; + ) + ); } /** @@ -110,17 +110,17 @@ public function testChunkedEncoding(array $strings, $expected = "Wikipedia in\r\ public function provideInvalidChunkedEncoding() { - return [ - 'chunk-body-longer-than-header-suggests' => [ - ["4\r\nWiwot40n98w3498tw3049nyn039409t34\r\n", "ki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"], - ], - 'invalid-header-charactrrs' => [ + return array( + 'chunk-body-longer-than-header-suggests' => array( + array("4\r\nWiwot40n98w3498tw3049nyn039409t34\r\n", "ki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n"), + ), + 'invalid-header-charactrrs' => array( str_split("xyz\r\nWi\r\nki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n") - ], - 'header-chunk-to-long' => [ + ), + 'header-chunk-to-long' => array( str_split(str_repeat('a', 2015) . "\r\nWi\r\nki\r\n5\r\npedia\r\ne\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n") - ] - ]; + ) + ); } /** @@ -142,10 +142,10 @@ public function testInvalidChunkedEncoding(array $strings) public function provideZeroChunk() { - return [ - ['1-zero' => "0\r\n\r\n"], - ['random-zero' => str_repeat("0", rand(2, 10))."\r\n\r\n"] - ]; + return array( + array('1-zero' => "0\r\n\r\n"), + array('random-zero' => str_repeat("0", rand(2, 10))."\r\n\r\n") + ); } /** diff --git a/tests/RequestDataTest.php b/tests/RequestDataTest.php index 48ba9be..4db81cd 100644 --- a/tests/RequestDataTest.php +++ b/tests/RequestDataTest.php @@ -126,7 +126,7 @@ public function toStringReturnsHTTPRequestMessageWithHeadersInCustomCase() /** @test */ public function toStringReturnsHTTPRequestMessageWithProtocolVersionThroughConstructor() { - $requestData = new RequestData('GET', 'http://www.example.com', [], '1.1'); + $requestData = new RequestData('GET', 'http://www.example.com', array(), '1.1'); $expected = "GET / HTTP/1.1\r\n" . "Host: www.example.com\r\n" . diff --git a/tests/RequestTest.php b/tests/RequestTest.php index c55c53b..0ac5d09 100644 --- a/tests/RequestTest.php +++ b/tests/RequestTest.php @@ -634,8 +634,9 @@ private function successfulAsyncConnectionMock() ->with('www.example.com:80') ->will($this->returnValue($deferred->promise())); - return function () use ($deferred) { - $deferred->resolve($this->stream); + $stream = $this->stream; + return function () use ($deferred, $stream) { + $deferred->resolve($stream); }; } @@ -699,7 +700,7 @@ public function chunkedStreamDecoder() $this->stream->expects($this->once()) ->method('emit') - ->with('data', ["1\r\nb\r"]); + ->with('data', array("1\r\nb\r")); $request->handleData("HTTP/1.0 200 OK\r\n"); $request->handleData("Transfer-Encoding: chunked\r\n"); diff --git a/tests/ResponseTest.php b/tests/ResponseTest.php index d7ad6b8..a751ab6 100644 --- a/tests/ResponseTest.php +++ b/tests/ResponseTest.php @@ -64,9 +64,9 @@ public function responseShouldEmitEndEventOnEnd() $response->handleEnd(); $this->assertSame( - [ + array( 'Content-Type' => 'text/plain' - ], + ), $response->getHeaders() ); } @@ -89,9 +89,9 @@ public function closedResponseShouldNotBeResumedOrPaused() $response->pause(); $this->assertSame( - [ + array( 'content-type' => 'text/plain', - ], + ), $response->getHeaders() ); } @@ -106,10 +106,10 @@ public function chunkedEncodingResponse() '1.0', '200', 'ok', - [ + array( 'content-type' => 'text/plain', 'transfer-encoding' => 'chunked', - ] + ) ); $buffer = ''; @@ -123,9 +123,9 @@ public function chunkedEncodingResponse() $this->assertSame('Wiki', $buffer); $this->assertSame( - [ + array( 'content-type' => 'text/plain', - ], + ), $response->getHeaders() ); } From 7dd490916b07e7402b7143e1ad6803fdb50c5e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Fri, 9 Feb 2018 09:42:44 +0100 Subject: [PATCH 05/16] Prepare v0.5.8 release --- CHANGELOG.md | 9 +++++++++ README.md | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15db4d7..a923861 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 0.5.8 (2018-02-09) + +* Support legacy PHP 5.3 through PHP 7.2 and HHVM + (#126 and #127 by @clue) + +* Improve backwards compatibility with Promise v1 and + use RingCentral to improve interoperability with react/http. + (#124 and #125 by @clue) + ## 0.5.7 (2018-02-08) * Fix: Ignore excessive whitespace in chunk header for `Transfer-Encoding: chunked` diff --git a/README.md b/README.md index c8494f6..6ae1f97 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ The recommended way to install this library is [through Composer](https://getcom This will install the latest supported version: ```bash -$ composer require react/http-client:^0.5.7 +$ composer require react/http-client:^0.5.8 ``` See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. From 3d269081df9ff82ae37c87928814c8f8c2f5d0f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sat, 7 Apr 2018 15:47:12 +0200 Subject: [PATCH 06/16] Support legacy HTTP servers that use only LF instead of CRLF --- src/Request.php | 3 ++- tests/FunctionalIntegrationTest.php | 23 +++++++++++++++++++++++ tests/TestCase.php | 11 +++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/Request.php b/src/Request.php index ea4d50b..caa242b 100644 --- a/src/Request.php +++ b/src/Request.php @@ -134,7 +134,8 @@ public function handleData($data) { $this->buffer .= $data; - if (false !== strpos($this->buffer, "\r\n\r\n")) { + // buffer until double CRLF (or double LF for compatibility with legacy servers) + if (false !== strpos($this->buffer, "\r\n\r\n") || false !== strpos($this->buffer, "\n\n")) { try { list($response, $bodyChunk) = $this->parseResponse($this->buffer); } catch (\InvalidArgumentException $exception) { diff --git a/tests/FunctionalIntegrationTest.php b/tests/FunctionalIntegrationTest.php index 1ed2228..1deebc7 100644 --- a/tests/FunctionalIntegrationTest.php +++ b/tests/FunctionalIntegrationTest.php @@ -29,6 +29,29 @@ public function testRequestToLocalhostEmitsSingleRemoteConnection() $loop->run(); } + public function testRequestLegacyHttpServerWithOnlyLineFeedReturnsSuccessfulResponse() + { + $loop = Factory::create(); + + $server = new Server(0, $loop); + $server->on('connection', function (ConnectionInterface $conn) use ($server) { + $conn->end("HTTP/1.0 200 OK\n\nbody"); + $server->close(); + }); + + $client = new Client($loop); + $request = $client->request('GET', str_replace('tcp:', 'http:', $server->getAddress())); + + $once = $this->expectCallableOnceWith('body'); + $request->on('response', function (Response $response) use ($once) { + $response->on('data', $once); + }); + + $request->end(); + + $loop->run(); + } + /** @group internet */ public function testSuccessfulResponseEmitsEnd() { diff --git a/tests/TestCase.php b/tests/TestCase.php index 9e090bc..901f82f 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -26,6 +26,17 @@ protected function expectCallableOnce() return $mock; } + protected function expectCallableOnceWith($value) + { + $mock = $this->createCallableMock(); + $mock + ->expects($this->once()) + ->method('__invoke') + ->with($value); + + return $mock; + } + protected function expectCallableNever() { $mock = $this->createCallableMock(); From 7293f8d445c2bbe21a73c757b04e6cf6efd9d785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sat, 7 Apr 2018 17:31:26 +0200 Subject: [PATCH 07/16] Apply maximum test timeouts for integration tests --- composer.json | 4 ++- tests/FunctionalIntegrationTest.php | 55 ++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/composer.json b/composer.json index ecb19e5..4cd9d7f 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,9 @@ "ringcentral/psr7": "^1.2" }, "require-dev": { - "phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35" + "clue/block-react": "^1.2", + "phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35", + "react/promise-stream": "^1.1" }, "autoload": { "psr-4": { diff --git a/tests/FunctionalIntegrationTest.php b/tests/FunctionalIntegrationTest.php index 1deebc7..cc8d880 100644 --- a/tests/FunctionalIntegrationTest.php +++ b/tests/FunctionalIntegrationTest.php @@ -2,14 +2,37 @@ namespace React\Tests\HttpClient; +use Clue\React\Block; use React\EventLoop\Factory; use React\HttpClient\Client; use React\HttpClient\Response; +use React\Promise\Deferred; +use React\Promise\Stream; use React\Socket\Server; use React\Socket\ConnectionInterface; class FunctionalIntegrationTest extends TestCase { + /** + * Test timeout to use for local tests. + * + * In practice this would be near 0.001s, but let's leave some time in case + * the local system is currently busy. + * + * @var float + */ + const TIMEOUT_LOCAL = 1.0; + + /** + * Test timeout to use for remote (internet) tests. + * + * In pratice this should be below 1s, but this relies on infrastructure + * outside our control, so consider this a maximum to avoid running for hours. + * + * @var float + */ + const TIMEOUT_REMOTE = 10.0; + public function testRequestToLocalhostEmitsSingleRemoteConnection() { $loop = Factory::create(); @@ -24,9 +47,11 @@ public function testRequestToLocalhostEmitsSingleRemoteConnection() $client = new Client($loop); $request = $client->request('GET', 'http://localhost:' . $port); + + $promise = Stream\first($request, 'close'); $request->end(); - $loop->run(); + Block\await($promise, $loop, self::TIMEOUT_LOCAL); } public function testRequestLegacyHttpServerWithOnlyLineFeedReturnsSuccessfulResponse() @@ -47,9 +72,10 @@ public function testRequestLegacyHttpServerWithOnlyLineFeedReturnsSuccessfulResp $response->on('data', $once); }); + $promise = Stream\first($request, 'close'); $request->end(); - $loop->run(); + Block\await($promise, $loop, self::TIMEOUT_LOCAL); } /** @group internet */ @@ -65,9 +91,10 @@ public function testSuccessfulResponseEmitsEnd() $response->on('end', $once); }); + $promise = Stream\first($request, 'close'); $request->end(); - $loop->run(); + Block\await($promise, $loop, self::TIMEOUT_REMOTE); } /** @group internet */ @@ -79,11 +106,9 @@ public function testPostDataReturnsData() $data = str_repeat('.', 33000); $request = $client->request('POST', 'https://' . (mt_rand(0, 1) === 0 ? 'eu.' : '') . 'httpbin.org/post', array('Content-Length' => strlen($data))); - $buffer = ''; - $request->on('response', function (Response $response) use (&$buffer) { - $response->on('data', function ($chunk) use (&$buffer) { - $buffer .= $chunk; - }); + $deferred = new Deferred(); + $request->on('response', function (Response $response) use ($deferred) { + $deferred->resolve(Stream\buffer($response)); }); $request->on('error', 'printf'); @@ -91,7 +116,7 @@ public function testPostDataReturnsData() $request->end($data); - $loop->run(); + $buffer = Block\await($deferred->promise(), $loop, self::TIMEOUT_REMOTE); $this->assertNotEquals('', $buffer); @@ -110,11 +135,9 @@ public function testPostJsonReturnsData() $data = json_encode(array('numbers' => range(1, 50))); $request = $client->request('POST', 'https://httpbin.org/post', array('Content-Length' => strlen($data), 'Content-Type' => 'application/json')); - $buffer = ''; - $request->on('response', function (Response $response) use (&$buffer) { - $response->on('data', function ($chunk) use (&$buffer) { - $buffer .= $chunk; - }); + $deferred = new Deferred(); + $request->on('response', function (Response $response) use ($deferred) { + $deferred->resolve(Stream\buffer($response)); }); $request->on('error', 'printf'); @@ -122,7 +145,7 @@ public function testPostJsonReturnsData() $request->end($data); - $loop->run(); + $buffer = Block\await($deferred->promise(), $loop, self::TIMEOUT_REMOTE); $this->assertNotEquals('', $buffer); @@ -142,7 +165,5 @@ public function testCancelPendingConnectionEmitsClose() $request->on('close', $this->expectCallableOnce()); $request->end(); $request->close(); - - $loop->run(); } } From f8e81a022b61938e0b37c94c6351fc170b7d87f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Tue, 10 Apr 2018 13:38:54 +0200 Subject: [PATCH 08/16] Prepare v0.5.9 release --- CHANGELOG.md | 8 ++++++++ README.md | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a923861..d97d680 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.5.9 (2018-04-10) + +* Feature: Support legacy HTTP servers that use only `LF` instead of `CRLF`. + (#130 by @clue) + +* Improve test suite by applying maximum test timeouts for integration tests. + (#131 by @clue) + ## 0.5.8 (2018-02-09) * Support legacy PHP 5.3 through PHP 7.2 and HHVM diff --git a/README.md b/README.md index 6ae1f97..a8926c0 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ The recommended way to install this library is [through Composer](https://getcom This will install the latest supported version: ```bash -$ composer require react/http-client:^0.5.8 +$ composer require react/http-client:^0.5.9 ``` See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. From ef902e384c74af3513e049a991ebcad6a5d055ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sun, 27 Jan 2019 17:24:20 +0100 Subject: [PATCH 09/16] Link to clue/reactphp-buzz for higher-level HTTP client --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index a8926c0..eb45105 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,13 @@ Event-driven, streaming HTTP client for [ReactPHP](https://reactphp.org). +> Note that this is a very low-level HTTP client implementation that is currently + undergoing some major changes. In the meantime, we recommend using + [clue/reactphp-buzz](https://github.com/clue/reactphp-buzz) as a higher-level + HTTP client abstraction (which happens to build on top of this project). It + provides a Promise-based interface and common PSR-7 message abstraction which + makes getting started much easier. + **Table of Contents** * [Basic usage](#basic-usage) From 6826c75ad85245172fc2d1e91573baf297436248 Mon Sep 17 00:00:00 2001 From: Sam Reed Date: Sun, 1 Dec 2019 01:59:57 +0000 Subject: [PATCH 10/16] Add .gitattributes to exclude dev files from exports --- .gitattributes | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..f2f51dd --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +/.gitattributes export-ignore +/.gitignore export-ignore +/.travis.yml export-ignore +/examples export-ignore +/phpunit.xml.dist export-ignore +/tests export-ignore From c24f511245d019929aba02294acc8e263fdf05de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sat, 11 Jan 2020 18:11:46 +0100 Subject: [PATCH 11/16] Avoid unneeded warning when decoding invalid data on PHP 7.4 --- .travis.yml | 2 ++ composer.json | 2 +- phpunit.xml.dist | 1 - src/ChunkedStreamDecoder.php | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 46a0486..2715358 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,8 @@ php: - 7.0 - 7.1 - 7.2 + - 7.3 + - 7.4 - nightly # ignore errors, see below - hhvm # ignore errors, see below diff --git a/composer.json b/composer.json index 4cd9d7f..673e61c 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ }, "require-dev": { "clue/block-react": "^1.2", - "phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35", + "phpunit/phpunit": "^7.0 || ^6.4 || ^5.7 || ^4.8.35", "react/promise-stream": "^1.1" }, "autoload": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index cba6d4d..79c0ee6 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -8,7 +8,6 @@ convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" - syntaxCheck="false" bootstrap="tests/bootstrap.php" > diff --git a/src/ChunkedStreamDecoder.php b/src/ChunkedStreamDecoder.php index a96592e..fc76d52 100644 --- a/src/ChunkedStreamDecoder.php +++ b/src/ChunkedStreamDecoder.php @@ -111,7 +111,7 @@ protected function iterateBuffer() } } $this->nextChunkIsLength = false; - if (dechex(hexdec($lengthChunk)) !== strtolower($lengthChunk)) { + if (dechex(@hexdec($lengthChunk)) !== strtolower($lengthChunk)) { $this->emit('error', array( new Exception('Unable to validate "' . $lengthChunk . '" as chunk length header'), )); From 83bcf79c957cb72d96e5fb17cd38814f64155eea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Fri, 10 Jan 2020 17:39:44 +0100 Subject: [PATCH 12/16] Simplify test matrix and test setup --- .travis.yml | 27 +++++++++++++-------------- composer.json | 5 +++++ phpunit.xml.dist | 2 +- tests/bootstrap.php | 7 ------- 4 files changed, 19 insertions(+), 22 deletions(-) delete mode 100644 tests/bootstrap.php diff --git a/.travis.yml b/.travis.yml index 2715358..364429b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,18 +1,5 @@ language: php -php: -# - 5.3 # requires old distro - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - 7.1 - - 7.2 - - 7.3 - - 7.4 - - nightly # ignore errors, see below - - hhvm # ignore errors, see below - # lock distro so new future defaults will not break the build dist: trusty @@ -20,9 +7,21 @@ matrix: include: - php: 5.3 dist: precise + - php: 5.4 + - php: 5.5 + - php: 5.6 + - php: 7.0 + - php: 7.1 + - php: 7.2 + - php: 7.3 + - php: 7.4 + - php: nightly + - php: hhvm-3.18 + install: + - composer require phpunit/phpunit:^5 --dev --no-interaction # requires legacy phpunit allow_failures: - php: nightly - - php: hhvm + - php: hhvm-3.18 install: - composer install --no-interaction diff --git a/composer.json b/composer.json index 673e61c..9207639 100644 --- a/composer.json +++ b/composer.json @@ -21,5 +21,10 @@ "psr-4": { "React\\HttpClient\\": "src" } + }, + "autoload-dev": { + "psr-4": { + "React\\Tests\\HttpClient\\": "tests" + } } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 79c0ee6..04d426b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -8,7 +8,7 @@ convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" - bootstrap="tests/bootstrap.php" + bootstrap="vendor/autoload.php" > diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index e3bed44..0000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,7 +0,0 @@ -addPsr4('React\\Tests\\HttpClient\\', __DIR__); From f16ab55150ec369f8f9b5db64972f248691093b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Tue, 14 Jan 2020 09:36:16 +0100 Subject: [PATCH 13/16] Prepare v0.5.10 release --- CHANGELOG.md | 14 ++++++++++++++ README.md | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d97d680..53eb29b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 0.5.10 (2020-01-14) + +* Fix: Avoid unneeded warning when decoding invalid data on PHP 7.4. + (#150 by @clue) + +* Add `.gitattributes` to exclude dev files from exports. + (#149 by @reedy) + +* Link to clue/reactphp-buzz for higher-level HTTP client. + (#139 by @clue) + +* Improve test suite by simplifying test matrix and test setup. + (#151 by @clue) + ## 0.5.9 (2018-04-10) * Feature: Support legacy HTTP servers that use only `LF` instead of `CRLF`. diff --git a/README.md b/README.md index eb45105..70a7c53 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ The recommended way to install this library is [through Composer](https://getcom This will install the latest supported version: ```bash -$ composer require react/http-client:^0.5.9 +$ composer require react/http-client:^0.5.10 ``` See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. From fc3e5d01688655c2ae73b5650ca567736c62ffac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sun, 6 Sep 2020 12:05:11 +0200 Subject: [PATCH 14/16] Add deprecation notice to suggest HTTP component instead --- README.md | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 70a7c53..9ce6381 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,48 @@ -# HttpClient +# Deprecation notice + +This package has now been migrated over to +[react/http](https://github.com/reactphp/http) +and only exists for BC reasons. + +```bash +$ composer require react/http +``` + +If you've previously used this package, upgrading may take a moment or two. +The new API has been updated to use Promises and PSR-7 message abstractions. +This means it's now more powerful and easier to use than ever: + +```php +// old +$client = new React\HttpClient\Client($loop); +$request = $client->request('GET', 'https://example.com/'); +$request->on('response', function ($response) { + $response->on('data', function ($chunk) { + echo $chunk; + }); +}); +$request->end(); + +// new +$browser = new React\Http\Browser($loop); +$browser->get('https://example.com/')->then(function (Psr\Http\Message\ResponseInterface $response) { + echo $response->getBody(); +}); +``` + +See [react/http](https://github.com/reactphp/http#client-usage) for more details. + +The below documentation applies to the last release of this package. +Further development will take place in the updated +[react/http](https://github.com/reactphp/http), +so you're highly recommended to upgrade as soon as possible. + +# Deprecated HttpClient [![Build Status](https://travis-ci.org/reactphp/http-client.svg?branch=master)](https://travis-ci.org/reactphp/http-client) Event-driven, streaming HTTP client for [ReactPHP](https://reactphp.org). -> Note that this is a very low-level HTTP client implementation that is currently - undergoing some major changes. In the meantime, we recommend using - [clue/reactphp-buzz](https://github.com/clue/reactphp-buzz) as a higher-level - HTTP client abstraction (which happens to build on top of this project). It - provides a Promise-based interface and common PSR-7 message abstraction which - makes getting started much easier. - **Table of Contents** * [Basic usage](#basic-usage) From 7c2ccd0ddb4e7daa106acb6bbd163a3c073201b9 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 7 Apr 2021 16:28:13 +0200 Subject: [PATCH 15/16] Minimal fix for PHP 8 --- src/ChunkedStreamDecoder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ChunkedStreamDecoder.php b/src/ChunkedStreamDecoder.php index fc76d52..bc150ad 100644 --- a/src/ChunkedStreamDecoder.php +++ b/src/ChunkedStreamDecoder.php @@ -111,7 +111,7 @@ protected function iterateBuffer() } } $this->nextChunkIsLength = false; - if (dechex(@hexdec($lengthChunk)) !== strtolower($lengthChunk)) { + if (dechex((int)@hexdec($lengthChunk)) !== strtolower($lengthChunk)) { $this->emit('error', array( new Exception('Unable to validate "' . $lengthChunk . '" as chunk length header'), )); From 23dddb415b9bd36c81d1c78df63143e65702aa4b Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 7 Apr 2021 18:49:17 +0200 Subject: [PATCH 16/16] Prepare v0.5.11 release --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53eb29b..5a71f99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.5.11 (2021-04-07) + +* Fix: Minimal fix for PHP 8 + (#154 by @remicollet) + +* Documentation: Add deprecation notice to suggest HTTP component instead + (#153 by @clue) + ## 0.5.10 (2020-01-14) * Fix: Avoid unneeded warning when decoding invalid data on PHP 7.4. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy