From bf973107f0fd2eac241fc4a8d5229f6fd254b655 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Thu, 6 Oct 2016 07:48:11 +0200 Subject: [PATCH 01/17] Streaming parser bufferedsink --- src/StreamingBodyParser/BufferedSink.php | 90 ++++++++++++++++ .../StreamingBodyParser/BufferedSinkTest.php | 100 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 src/StreamingBodyParser/BufferedSink.php create mode 100644 tests/StreamingBodyParser/BufferedSinkTest.php diff --git a/src/StreamingBodyParser/BufferedSink.php b/src/StreamingBodyParser/BufferedSink.php new file mode 100644 index 00000000..aecc9663 --- /dev/null +++ b/src/StreamingBodyParser/BufferedSink.php @@ -0,0 +1,90 @@ + [], + 'files' => [], + 'body' => '', + ]); + } + + $deferred = new Deferred(); + $postFields = []; + $files = []; + $body = ''; + $parser->on('post', function ($key, $value) use (&$postFields) { + self::extractPost($postFields, $key, $value); + }); + $parser->on('file', function ($name, File $file) use (&$files) { + StreamBufferedSink::createPromise($file->getStream())->then(function ($buffer) use ($name, $file, &$files) { + $files[] = [ + 'name' => $name, + 'file' => $file, + 'buffer' => $buffer, + ]; + }); + }); + $parser->on('body', function ($rawBody) use (&$body) { + $body = $rawBody; + }); + $parser->on('end', function () use ($deferred, &$postFields, &$files, &$body) { + $deferred->resolve([ + 'post' => $postFields, + 'files' => $files, + 'body' => $body, + ]); + }); + + return $deferred->promise(); + } + + public static function extractPost(&$postFields, $key, $value) + { + $chunks = explode('[', $key); + if (count($chunks) == 1) { + $postFields[$key] = $value; + return; + } + + $chunkKey = $chunks[0]; + if (!isset($postFields[$chunkKey])) { + $postFields[$chunkKey] = []; + } + + $parent = &$postFields; + for ($i = 1; $i < count($chunks); $i++) { + $previousChunkKey = $chunkKey; + if (!isset($parent[$previousChunkKey])) { + $parent[$previousChunkKey] = []; + } + $parent = &$parent[$previousChunkKey]; + $chunkKey = $chunks[$i]; + + if ($chunkKey == ']') { + $parent[] = $value; + return; + } + + $chunkKey = rtrim($chunkKey, ']'); + if ($i == count($chunks) - 1) { + $parent[$chunkKey] = $value; + return; + } + } + } +} diff --git a/tests/StreamingBodyParser/BufferedSinkTest.php b/tests/StreamingBodyParser/BufferedSinkTest.php new file mode 100644 index 00000000..27623bb8 --- /dev/null +++ b/tests/StreamingBodyParser/BufferedSinkTest.php @@ -0,0 +1,100 @@ +assertSame([ + 'post' => [], + 'files' => [], + 'body' => '', + ], $result); + } + + public function testDeferredStream() + { + $parser = new DummyParser(new Request('get', 'http://example.com')); + $deferredStream = BufferedSink::createPromise($parser); + $parser->emit('post', ['foo', 'bar']); + $parser->emit('post', ['array[]', 'foo']); + $parser->emit('post', ['array[]', 'bar']); + $parser->emit('post', ['dem[two]', 'bar']); + $parser->emit('post', ['dom[two][]', 'bar']); + + $stream = new ThroughStream(); + $file = new File('bar.ext', 'text', $stream); + $parser->emit('file', ['foo', $file]); + $stream->end('foo.bar'); + + $parser->emit('body', ['abc']); + + $parser->emit('end'); + + $result = Block\await($deferredStream, Factory::create(), 10); + $this->assertSame([ + 'foo' => 'bar', + 'array' => [ + 'foo', + 'bar', + ], + 'dem' => [ + 'two' => 'bar', + ], + 'dom' => [ + 'two' => [ + 'bar', + ], + ], + ], $result['post']); + + $this->assertSame('foo', $result['files'][0]['name']); + $this->assertSame('bar.ext', $result['files'][0]['file']->getFilename()); + $this->assertSame('text', $result['files'][0]['file']->getContentType()); + $this->assertSame('foo.bar', $result['files'][0]['buffer']); + + $this->assertSame('abc', $result['body']); + } + + public function testExtractPost() + { + $postFields = []; + BufferedSink::extractPost($postFields, 'dem', 'value'); + BufferedSink::extractPost($postFields, 'dom[one][two][]', 'value_a'); + BufferedSink::extractPost($postFields, 'dom[one][two][]', 'value_b'); + BufferedSink::extractPost($postFields, 'dam[]', 'value_a'); + BufferedSink::extractPost($postFields, 'dam[]', 'value_b'); + BufferedSink::extractPost($postFields, 'dum[sum]', 'value'); + $this->assertSame([ + 'dem' => 'value', + 'dom' => [ + 'one' => [ + 'two' => [ + 'value_a', + 'value_b', + ], + ], + ], + 'dam' => [ + 'value_a', + 'value_b', + ], + 'dum' => [ + 'sum' => 'value', + ], + ], $postFields); + } +} From 9207588f151df93f6383a418abdd56b4e8c3e40a Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 07:52:30 +0200 Subject: [PATCH 02/17] BodyBufferedSink: https://github.com/reactphp/http/pull/73#issuecomment-256144946 --- src/StreamingBodyParser/BodyBufferedSink.php | 32 +++++++++++++++++ .../BodyBufferedSinkTest.php | 36 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/StreamingBodyParser/BodyBufferedSink.php create mode 100644 tests/StreamingBodyParser/BodyBufferedSinkTest.php diff --git a/src/StreamingBodyParser/BodyBufferedSink.php b/src/StreamingBodyParser/BodyBufferedSink.php new file mode 100644 index 00000000..b8763964 --- /dev/null +++ b/src/StreamingBodyParser/BodyBufferedSink.php @@ -0,0 +1,32 @@ +on('body', function ($rawBody) use (&$body) { + $body = $rawBody; + }); + $parser->on('end', function () use ($deferred, &$postFields, &$files, &$body) { + $deferred->resolve($body); + }); + + return $deferred->promise(); + } +} \ No newline at end of file diff --git a/tests/StreamingBodyParser/BodyBufferedSinkTest.php b/tests/StreamingBodyParser/BodyBufferedSinkTest.php new file mode 100644 index 00000000..8b7bb9aa --- /dev/null +++ b/tests/StreamingBodyParser/BodyBufferedSinkTest.php @@ -0,0 +1,36 @@ +assertSame('', $result); + } + + public function testDeferredStream() + { + $parser = new DummyParser(new Request('get', 'http://example.com')); + $deferredStream = BufferedSink::createPromise($parser); + + $parser->emit('body', ['abc']); + $parser->emit('end'); + + $result = Block\await($deferredStream, Factory::create(), 10); + + $this->assertSame('abc', $result['body']); + } +} From b046c8457a23232f2de9735be0e13624c7f2a7e5 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 07:55:12 +0200 Subject: [PATCH 03/17] Removed old vars I forgot to removed :X --- src/StreamingBodyParser/BodyBufferedSink.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StreamingBodyParser/BodyBufferedSink.php b/src/StreamingBodyParser/BodyBufferedSink.php index b8763964..9424feb1 100644 --- a/src/StreamingBodyParser/BodyBufferedSink.php +++ b/src/StreamingBodyParser/BodyBufferedSink.php @@ -23,7 +23,7 @@ public static function createPromise(ParserInterface $parser) $parser->on('body', function ($rawBody) use (&$body) { $body = $rawBody; }); - $parser->on('end', function () use ($deferred, &$postFields, &$files, &$body) { + $parser->on('end', function () use ($deferred, &$body) { $deferred->resolve($body); }); From 0f54149a0c6af717471687b7d71ddb6d111eae3a Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 07:56:06 +0200 Subject: [PATCH 04/17] Correct PostBufferedSinkTest class name --- tests/StreamingBodyParser/BufferedSinkTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/StreamingBodyParser/BufferedSinkTest.php b/tests/StreamingBodyParser/BufferedSinkTest.php index 27623bb8..19bef1a3 100644 --- a/tests/StreamingBodyParser/BufferedSinkTest.php +++ b/tests/StreamingBodyParser/BufferedSinkTest.php @@ -11,7 +11,7 @@ use React\Stream\ThroughStream; use React\Tests\Http\TestCase; -class DeferredStreamTest extends TestCase +class BufferedSinkTest extends TestCase { public function testDoneParser() { From b775b9664e1781d07b1c5492805ba6078e2ead1d Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 07:57:26 +0200 Subject: [PATCH 05/17] $result now contains the body not an array with different types of data in it --- tests/StreamingBodyParser/BodyBufferedSinkTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/StreamingBodyParser/BodyBufferedSinkTest.php b/tests/StreamingBodyParser/BodyBufferedSinkTest.php index 8b7bb9aa..de22b6a2 100644 --- a/tests/StreamingBodyParser/BodyBufferedSinkTest.php +++ b/tests/StreamingBodyParser/BodyBufferedSinkTest.php @@ -31,6 +31,6 @@ public function testDeferredStream() $result = Block\await($deferredStream, Factory::create(), 10); - $this->assertSame('abc', $result['body']); + $this->assertSame('abc', $result); } } From ee9039f9034799ce5eeca0b522d831849e989fdf Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 07:58:31 +0200 Subject: [PATCH 06/17] PostBufferedSink: https://github.com/reactphp/http/pull/73#issuecomment-256144946 --- src/StreamingBodyParser/PostBufferedSink.php | 66 +++++++++++++++ .../PostBufferedSinkTest.php | 80 +++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 src/StreamingBodyParser/PostBufferedSink.php create mode 100644 tests/StreamingBodyParser/PostBufferedSinkTest.php diff --git a/src/StreamingBodyParser/PostBufferedSink.php b/src/StreamingBodyParser/PostBufferedSink.php new file mode 100644 index 00000000..6b1a9b86 --- /dev/null +++ b/src/StreamingBodyParser/PostBufferedSink.php @@ -0,0 +1,66 @@ +on('post', function ($key, $value) use (&$postFields) { + self::extractPost($postFields, $key, $value); + }); + $parser->on('end', function () use ($deferred, &$postFields) { + $deferred->resolve($postFields); + }); + + return $deferred->promise(); + } + + public static function extractPost(&$postFields, $key, $value) + { + $chunks = explode('[', $key); + if (count($chunks) == 1) { + $postFields[$key] = $value; + return; + } + + $chunkKey = $chunks[0]; + if (!isset($postFields[$chunkKey])) { + $postFields[$chunkKey] = []; + } + + $parent = &$postFields; + for ($i = 1; $i < count($chunks); $i++) { + $previousChunkKey = $chunkKey; + if (!isset($parent[$previousChunkKey])) { + $parent[$previousChunkKey] = []; + } + $parent = &$parent[$previousChunkKey]; + $chunkKey = $chunks[$i]; + + if ($chunkKey == ']') { + $parent[] = $value; + return; + } + + $chunkKey = rtrim($chunkKey, ']'); + if ($i == count($chunks) - 1) { + $parent[$chunkKey] = $value; + return; + } + } + } +} diff --git a/tests/StreamingBodyParser/PostBufferedSinkTest.php b/tests/StreamingBodyParser/PostBufferedSinkTest.php new file mode 100644 index 00000000..971b841c --- /dev/null +++ b/tests/StreamingBodyParser/PostBufferedSinkTest.php @@ -0,0 +1,80 @@ +assertSame([], $result); + } + + public function testDeferredStream() + { + $parser = new DummyParser(new Request('get', 'http://example.com')); + $deferredStream = BufferedSink::createPromise($parser); + $parser->emit('post', ['foo', 'bar']); + $parser->emit('post', ['array[]', 'foo']); + $parser->emit('post', ['array[]', 'bar']); + $parser->emit('post', ['dem[two]', 'bar']); + $parser->emit('post', ['dom[two][]', 'bar']); + + $parser->emit('end'); + + $result = Block\await($deferredStream, Factory::create(), 10); + $this->assertSame([ + 'foo' => 'bar', + 'array' => [ + 'foo', + 'bar', + ], + 'dem' => [ + 'two' => 'bar', + ], + 'dom' => [ + 'two' => [ + 'bar', + ], + ], + ], $result); + } + + public function testExtractPost() + { + $postFields = []; + BufferedSink::extractPost($postFields, 'dem', 'value'); + BufferedSink::extractPost($postFields, 'dom[one][two][]', 'value_a'); + BufferedSink::extractPost($postFields, 'dom[one][two][]', 'value_b'); + BufferedSink::extractPost($postFields, 'dam[]', 'value_a'); + BufferedSink::extractPost($postFields, 'dam[]', 'value_b'); + BufferedSink::extractPost($postFields, 'dum[sum]', 'value'); + $this->assertSame([ + 'dem' => 'value', + 'dom' => [ + 'one' => [ + 'two' => [ + 'value_a', + 'value_b', + ], + ], + ], + 'dam' => [ + 'value_a', + 'value_b', + ], + 'dum' => [ + 'sum' => 'value', + ], + ], $postFields); + } +} From 11fb097c273a1134596cac6508adab448727286e Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 07:58:49 +0200 Subject: [PATCH 07/17] Removed unused uses --- tests/StreamingBodyParser/BodyBufferedSinkTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/StreamingBodyParser/BodyBufferedSinkTest.php b/tests/StreamingBodyParser/BodyBufferedSinkTest.php index de22b6a2..3349c3fc 100644 --- a/tests/StreamingBodyParser/BodyBufferedSinkTest.php +++ b/tests/StreamingBodyParser/BodyBufferedSinkTest.php @@ -4,11 +4,9 @@ use Clue\React\Block; use React\EventLoop\Factory; -use React\Http\File; use React\Http\StreamingBodyParser\BufferedSink; use React\Http\StreamingBodyParser\NoBodyParser; use React\Http\Request; -use React\Stream\ThroughStream; use React\Tests\Http\TestCase; class BodyBufferedSinkTest extends TestCase From 0619c14d7f958d3b851a5ff1449822c6490be036 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 08:00:05 +0200 Subject: [PATCH 08/17] Then => done: https://github.com/reactphp/http/pull/73#discussion_r84976233 --- src/StreamingBodyParser/BufferedSink.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StreamingBodyParser/BufferedSink.php b/src/StreamingBodyParser/BufferedSink.php index aecc9663..ce08d14f 100644 --- a/src/StreamingBodyParser/BufferedSink.php +++ b/src/StreamingBodyParser/BufferedSink.php @@ -31,7 +31,7 @@ public static function createPromise(ParserInterface $parser) self::extractPost($postFields, $key, $value); }); $parser->on('file', function ($name, File $file) use (&$files) { - StreamBufferedSink::createPromise($file->getStream())->then(function ($buffer) use ($name, $file, &$files) { + StreamBufferedSink::createPromise($file->getStream())->done(function ($buffer) use ($name, $file, &$files) { $files[] = [ 'name' => $name, 'file' => $file, From 64ce2d6d05e08618b74339d459e9c837eaccad29 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 08:02:17 +0200 Subject: [PATCH 09/17] Corrected return comment for BodyBufferedSink::createPromise --- src/StreamingBodyParser/BodyBufferedSink.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StreamingBodyParser/BodyBufferedSink.php b/src/StreamingBodyParser/BodyBufferedSink.php index 9424feb1..4ae3db7c 100644 --- a/src/StreamingBodyParser/BodyBufferedSink.php +++ b/src/StreamingBodyParser/BodyBufferedSink.php @@ -9,7 +9,7 @@ class BodyBufferedSink { /** * @param ParserInterface $parser - * @return PromiseInterface + * @return Promise\PromiseInterface */ public static function createPromise(ParserInterface $parser) { From b1d8e0e75a7b666512ae2b1e4de846ba6853369b Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 08:02:30 +0200 Subject: [PATCH 10/17] Corrected return comment for PostBufferedSink::createPromise --- src/StreamingBodyParser/PostBufferedSink.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StreamingBodyParser/PostBufferedSink.php b/src/StreamingBodyParser/PostBufferedSink.php index 6b1a9b86..2c483da0 100644 --- a/src/StreamingBodyParser/PostBufferedSink.php +++ b/src/StreamingBodyParser/PostBufferedSink.php @@ -8,7 +8,7 @@ class PostBufferedSink { /** * @param ParserInterface $parser - * @return PromiseInterface + * @return Promise\PromiseInterface */ public static function createPromise(ParserInterface $parser) { From 75facbb73a09d5c59e5413bf908bf4db8e4121c4 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 08:04:23 +0200 Subject: [PATCH 11/17] Call the correct sink for body buffered sink test --- tests/StreamingBodyParser/BodyBufferedSinkTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/StreamingBodyParser/BodyBufferedSinkTest.php b/tests/StreamingBodyParser/BodyBufferedSinkTest.php index 3349c3fc..8bec4fe1 100644 --- a/tests/StreamingBodyParser/BodyBufferedSinkTest.php +++ b/tests/StreamingBodyParser/BodyBufferedSinkTest.php @@ -4,7 +4,7 @@ use Clue\React\Block; use React\EventLoop\Factory; -use React\Http\StreamingBodyParser\BufferedSink; +use React\Http\StreamingBodyParser\BodyBufferedSink; use React\Http\StreamingBodyParser\NoBodyParser; use React\Http\Request; use React\Tests\Http\TestCase; @@ -14,7 +14,7 @@ class BodyBufferedSinkTest extends TestCase public function testDoneParser() { $parser = new NoBodyParser(new Request('get', 'http://example.com')); - $deferredStream = BufferedSink::createPromise($parser); + $deferredStream = BodyBufferedSink::createPromise($parser); $result = Block\await($deferredStream, Factory::create(), 10); $this->assertSame('', $result); } @@ -22,7 +22,7 @@ public function testDoneParser() public function testDeferredStream() { $parser = new DummyParser(new Request('get', 'http://example.com')); - $deferredStream = BufferedSink::createPromise($parser); + $deferredStream = BodyBufferedSink::createPromise($parser); $parser->emit('body', ['abc']); $parser->emit('end'); From 14c21114519073b535d9b914df05a1b3c69f19ae Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 08:05:10 +0200 Subject: [PATCH 12/17] Call the correct sink for post buffered sink test --- .../PostBufferedSinkTest.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/StreamingBodyParser/PostBufferedSinkTest.php b/tests/StreamingBodyParser/PostBufferedSinkTest.php index 971b841c..65417ec7 100644 --- a/tests/StreamingBodyParser/PostBufferedSinkTest.php +++ b/tests/StreamingBodyParser/PostBufferedSinkTest.php @@ -4,17 +4,17 @@ use Clue\React\Block; use React\EventLoop\Factory; -use React\Http\StreamingBodyParser\BufferedSink; +use React\Http\StreamingBodyParser\PostBufferedSink; use React\Http\StreamingBodyParser\NoBodyParser; use React\Http\Request; use React\Tests\Http\TestCase; -class PostBufferedSinkTest extends TestCase +class PostPostBufferedSinkTest extends TestCase { public function testDoneParser() { $parser = new NoBodyParser(new Request('get', 'http://example.com')); - $deferredStream = BufferedSink::createPromise($parser); + $deferredStream = PostBufferedSink::createPromise($parser); $result = Block\await($deferredStream, Factory::create(), 10); $this->assertSame([], $result); } @@ -22,7 +22,7 @@ public function testDoneParser() public function testDeferredStream() { $parser = new DummyParser(new Request('get', 'http://example.com')); - $deferredStream = BufferedSink::createPromise($parser); + $deferredStream = PostBufferedSink::createPromise($parser); $parser->emit('post', ['foo', 'bar']); $parser->emit('post', ['array[]', 'foo']); $parser->emit('post', ['array[]', 'bar']); @@ -52,12 +52,12 @@ public function testDeferredStream() public function testExtractPost() { $postFields = []; - BufferedSink::extractPost($postFields, 'dem', 'value'); - BufferedSink::extractPost($postFields, 'dom[one][two][]', 'value_a'); - BufferedSink::extractPost($postFields, 'dom[one][two][]', 'value_b'); - BufferedSink::extractPost($postFields, 'dam[]', 'value_a'); - BufferedSink::extractPost($postFields, 'dam[]', 'value_b'); - BufferedSink::extractPost($postFields, 'dum[sum]', 'value'); + PostBufferedSink::extractPost($postFields, 'dem', 'value'); + PostBufferedSink::extractPost($postFields, 'dom[one][two][]', 'value_a'); + PostBufferedSink::extractPost($postFields, 'dom[one][two][]', 'value_b'); + PostBufferedSink::extractPost($postFields, 'dam[]', 'value_a'); + PostBufferedSink::extractPost($postFields, 'dam[]', 'value_b'); + PostBufferedSink::extractPost($postFields, 'dum[sum]', 'value'); $this->assertSame([ 'dem' => 'value', 'dom' => [ From 21e943a15512b7d7df4672c15013592591afc38d Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Oct 2016 08:06:37 +0200 Subject: [PATCH 13/17] FileBufferedSink: https://github.com/reactphp/http/pull/73#issuecomment-256144946 --- src/StreamingBodyParser/FilesBufferedSink.php | 39 +++++++++++++++++ .../FilesBufferedSinkTest.php | 43 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 src/StreamingBodyParser/FilesBufferedSink.php create mode 100644 tests/StreamingBodyParser/FilesBufferedSinkTest.php diff --git a/src/StreamingBodyParser/FilesBufferedSink.php b/src/StreamingBodyParser/FilesBufferedSink.php new file mode 100644 index 00000000..8024314d --- /dev/null +++ b/src/StreamingBodyParser/FilesBufferedSink.php @@ -0,0 +1,39 @@ +on('file', function ($name, File $file) use (&$files) { + StreamBufferedSink::createPromise($file->getStream())->done(function ($buffer) use ($name, $file, &$files) { + $files[] = [ + 'name' => $name, + 'file' => $file, + 'buffer' => $buffer, + ]; + }); + }); + $parser->on('end', function () use ($deferred, &$files) { + $deferred->resolve($files); + }); + + return $deferred->promise(); + } +} diff --git a/tests/StreamingBodyParser/FilesBufferedSinkTest.php b/tests/StreamingBodyParser/FilesBufferedSinkTest.php new file mode 100644 index 00000000..e9b4eff9 --- /dev/null +++ b/tests/StreamingBodyParser/FilesBufferedSinkTest.php @@ -0,0 +1,43 @@ +assertSame([], $result); + } + + public function testDeferredStream() + { + $parser = new DummyParser(new Request('get', 'http://example.com')); + $deferredStream = FilesBufferedSink::createPromise($parser); + + $stream = new ThroughStream(); + $file = new File('bar.ext', 'text', $stream); + $parser->emit('file', ['foo', $file]); + $stream->end('foo.bar'); + + $parser->emit('end'); + + $result = Block\await($deferredStream, Factory::create(), 10); + + $this->assertSame('foo', $result['files'][0]['name']); + $this->assertSame('bar.ext', $result['files'][0]['file']->getFilename()); + $this->assertSame('text', $result['files'][0]['file']->getContentType()); + $this->assertSame('foo.bar', $result['files'][0]['buffer']); + } +} From 2437eef2228e5427bfb82fd498d09d3fc768c54c Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Thu, 27 Oct 2016 07:43:38 +0200 Subject: [PATCH 14/17] Append additional body calls --- src/StreamingBodyParser/BodyBufferedSink.php | 2 +- tests/StreamingBodyParser/BodyBufferedSinkTest.php | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/StreamingBodyParser/BodyBufferedSink.php b/src/StreamingBodyParser/BodyBufferedSink.php index 4ae3db7c..0cbc4dce 100644 --- a/src/StreamingBodyParser/BodyBufferedSink.php +++ b/src/StreamingBodyParser/BodyBufferedSink.php @@ -21,7 +21,7 @@ public static function createPromise(ParserInterface $parser) $body = ''; $parser->on('body', function ($rawBody) use (&$body) { - $body = $rawBody; + $body .= $rawBody; }); $parser->on('end', function () use ($deferred, &$body) { $deferred->resolve($body); diff --git a/tests/StreamingBodyParser/BodyBufferedSinkTest.php b/tests/StreamingBodyParser/BodyBufferedSinkTest.php index 8bec4fe1..cc63006b 100644 --- a/tests/StreamingBodyParser/BodyBufferedSinkTest.php +++ b/tests/StreamingBodyParser/BodyBufferedSinkTest.php @@ -31,4 +31,18 @@ public function testDeferredStream() $this->assertSame('abc', $result); } + + public function testDeferredStreamMultipleCalls() + { + $parser = new DummyParser(new Request('get', 'http://example.com')); + $deferredStream = BodyBufferedSink::createPromise($parser); + + $parser->emit('body', ['abc']); + $parser->emit('body', ['def']); + $parser->emit('end'); + + $result = Block\await($deferredStream, Factory::create(), 10); + + $this->assertSame('abcdef', $result); + } } From 1d9a18d03e7ae1f6e52e9fb800c38e36f99cc9e2 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Thu, 27 Oct 2016 07:47:34 +0200 Subject: [PATCH 15/17] NoBodyParser is no more --- src/StreamingBodyParser/BodyBufferedSink.php | 4 ---- src/StreamingBodyParser/FilesBufferedSink.php | 4 ---- src/StreamingBodyParser/PostBufferedSink.php | 4 ---- tests/StreamingBodyParser/BodyBufferedSinkTest.php | 8 -------- tests/StreamingBodyParser/FilesBufferedSinkTest.php | 8 -------- tests/StreamingBodyParser/PostBufferedSinkTest.php | 8 -------- 6 files changed, 36 deletions(-) diff --git a/src/StreamingBodyParser/BodyBufferedSink.php b/src/StreamingBodyParser/BodyBufferedSink.php index 0cbc4dce..b0b1122a 100644 --- a/src/StreamingBodyParser/BodyBufferedSink.php +++ b/src/StreamingBodyParser/BodyBufferedSink.php @@ -13,10 +13,6 @@ class BodyBufferedSink */ public static function createPromise(ParserInterface $parser) { - if ($parser instanceof NoBodyParser) { - return Promise\resolve(''); - } - $deferred = new Promise\Deferred(); $body = ''; diff --git a/src/StreamingBodyParser/FilesBufferedSink.php b/src/StreamingBodyParser/FilesBufferedSink.php index 8024314d..fc5d1948 100644 --- a/src/StreamingBodyParser/FilesBufferedSink.php +++ b/src/StreamingBodyParser/FilesBufferedSink.php @@ -14,10 +14,6 @@ class FilesBufferedSink */ public static function createPromise(ParserInterface $parser) { - if ($parser instanceof NoBodyParser) { - return Promise\resolve([]); - } - $deferred = new Promise\Deferred(); $files = []; diff --git a/src/StreamingBodyParser/PostBufferedSink.php b/src/StreamingBodyParser/PostBufferedSink.php index 2c483da0..c4148e51 100644 --- a/src/StreamingBodyParser/PostBufferedSink.php +++ b/src/StreamingBodyParser/PostBufferedSink.php @@ -12,10 +12,6 @@ class PostBufferedSink */ public static function createPromise(ParserInterface $parser) { - if ($parser instanceof NoBodyParser) { - return Promise\resolve([]); - } - $deferred = new Promise\Deferred(); $postFields = []; diff --git a/tests/StreamingBodyParser/BodyBufferedSinkTest.php b/tests/StreamingBodyParser/BodyBufferedSinkTest.php index cc63006b..e656cba5 100644 --- a/tests/StreamingBodyParser/BodyBufferedSinkTest.php +++ b/tests/StreamingBodyParser/BodyBufferedSinkTest.php @@ -11,14 +11,6 @@ class BodyBufferedSinkTest extends TestCase { - public function testDoneParser() - { - $parser = new NoBodyParser(new Request('get', 'http://example.com')); - $deferredStream = BodyBufferedSink::createPromise($parser); - $result = Block\await($deferredStream, Factory::create(), 10); - $this->assertSame('', $result); - } - public function testDeferredStream() { $parser = new DummyParser(new Request('get', 'http://example.com')); diff --git a/tests/StreamingBodyParser/FilesBufferedSinkTest.php b/tests/StreamingBodyParser/FilesBufferedSinkTest.php index e9b4eff9..aa42f912 100644 --- a/tests/StreamingBodyParser/FilesBufferedSinkTest.php +++ b/tests/StreamingBodyParser/FilesBufferedSinkTest.php @@ -13,14 +13,6 @@ class FilesBufferedSinkTest extends TestCase { - public function testDoneParser() - { - $parser = new NoBodyParser(new Request('get', 'http://example.com')); - $deferredStream = FilesBufferedSink::createPromise($parser); - $result = Block\await($deferredStream, Factory::create(), 10); - $this->assertSame([], $result); - } - public function testDeferredStream() { $parser = new DummyParser(new Request('get', 'http://example.com')); diff --git a/tests/StreamingBodyParser/PostBufferedSinkTest.php b/tests/StreamingBodyParser/PostBufferedSinkTest.php index 65417ec7..6f490d13 100644 --- a/tests/StreamingBodyParser/PostBufferedSinkTest.php +++ b/tests/StreamingBodyParser/PostBufferedSinkTest.php @@ -11,14 +11,6 @@ class PostPostBufferedSinkTest extends TestCase { - public function testDoneParser() - { - $parser = new NoBodyParser(new Request('get', 'http://example.com')); - $deferredStream = PostBufferedSink::createPromise($parser); - $result = Block\await($deferredStream, Factory::create(), 10); - $this->assertSame([], $result); - } - public function testDeferredStream() { $parser = new DummyParser(new Request('get', 'http://example.com')); From e8c452bda8c51d0daa14821d2e228f5ee36712f1 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Thu, 27 Oct 2016 07:48:11 +0200 Subject: [PATCH 16/17] Resource BufferedSink as a handy wrapper around the other parser sinks as suggested by @jsor at https://github.com/reactphp/http/pull/73#issuecomment-256335617 --- src/StreamingBodyParser/BufferedSink.php | 83 +++--------------------- 1 file changed, 8 insertions(+), 75 deletions(-) diff --git a/src/StreamingBodyParser/BufferedSink.php b/src/StreamingBodyParser/BufferedSink.php index ce08d14f..e8a2d5e0 100644 --- a/src/StreamingBodyParser/BufferedSink.php +++ b/src/StreamingBodyParser/BufferedSink.php @@ -2,89 +2,22 @@ namespace React\Http\StreamingBodyParser; -use React\Http\File; -use React\Promise\Deferred; -use React\Promise\PromiseInterface; -use React\Stream\BufferedSink as StreamBufferedSink; +use React\Promise; class BufferedSink { /** * @param ParserInterface $parser - * @return PromiseInterface + * @return Promise\PromiseInterface */ public static function createPromise(ParserInterface $parser) { - if ($parser instanceof NoBodyParser) { - return \React\Promise\resolve([ - 'post' => [], - 'files' => [], - 'body' => '', - ]); - } + $promises = [ + 'body' => BodyBufferedSink::createPromise($parser), + 'post' => PostBufferedSink::createPromise($parser), + 'files' => FilesBufferedSink::createPromise($parser), + ]; - $deferred = new Deferred(); - $postFields = []; - $files = []; - $body = ''; - $parser->on('post', function ($key, $value) use (&$postFields) { - self::extractPost($postFields, $key, $value); - }); - $parser->on('file', function ($name, File $file) use (&$files) { - StreamBufferedSink::createPromise($file->getStream())->done(function ($buffer) use ($name, $file, &$files) { - $files[] = [ - 'name' => $name, - 'file' => $file, - 'buffer' => $buffer, - ]; - }); - }); - $parser->on('body', function ($rawBody) use (&$body) { - $body = $rawBody; - }); - $parser->on('end', function () use ($deferred, &$postFields, &$files, &$body) { - $deferred->resolve([ - 'post' => $postFields, - 'files' => $files, - 'body' => $body, - ]); - }); - - return $deferred->promise(); - } - - public static function extractPost(&$postFields, $key, $value) - { - $chunks = explode('[', $key); - if (count($chunks) == 1) { - $postFields[$key] = $value; - return; - } - - $chunkKey = $chunks[0]; - if (!isset($postFields[$chunkKey])) { - $postFields[$chunkKey] = []; - } - - $parent = &$postFields; - for ($i = 1; $i < count($chunks); $i++) { - $previousChunkKey = $chunkKey; - if (!isset($parent[$previousChunkKey])) { - $parent[$previousChunkKey] = []; - } - $parent = &$parent[$previousChunkKey]; - $chunkKey = $chunks[$i]; - - if ($chunkKey == ']') { - $parent[] = $value; - return; - } - - $chunkKey = rtrim($chunkKey, ']'); - if ($i == count($chunks) - 1) { - $parent[$chunkKey] = $value; - return; - } - } + return Promise\all($promises); } } From c2603b810f16a8de260443fd43052ba7e92b671c Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Thu, 27 Oct 2016 07:48:47 +0200 Subject: [PATCH 17/17] Type in PostBufferedSinkTest https://github.com/reactphp/http/pull/73#pullrequestreview-5845734 --- tests/StreamingBodyParser/PostBufferedSinkTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/StreamingBodyParser/PostBufferedSinkTest.php b/tests/StreamingBodyParser/PostBufferedSinkTest.php index 6f490d13..3b03554c 100644 --- a/tests/StreamingBodyParser/PostBufferedSinkTest.php +++ b/tests/StreamingBodyParser/PostBufferedSinkTest.php @@ -9,7 +9,7 @@ use React\Http\Request; use React\Tests\Http\TestCase; -class PostPostBufferedSinkTest extends TestCase +class PostBufferedSinkTest extends TestCase { public function testDeferredStream() {