diff --git a/composer.json b/composer.json index 3d431527..3cee9484 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "php": ">=5.3.0", "ringcentral/psr7": "^1.0", "react/socket": "^0.4", - "react/stream": "^0.4", + "react/stream": "^0.4.4", "evenement/evenement": "^2.0 || ^1.0" }, "autoload": { diff --git a/src/Server.php b/src/Server.php index f6e45a53..ba9daed5 100644 --- a/src/Server.php +++ b/src/Server.php @@ -63,6 +63,9 @@ public function handleRequest(ConnectionInterface $conn, Request $request, $body } $this->emit('request', array($request, $response)); - $request->emit('data', array($bodyBuffer)); + + if ($bodyBuffer !== '') { + $request->emit('data', array($bodyBuffer)); + } } } diff --git a/tests/ServerTest.php b/tests/ServerTest.php index b9234521..6974e2c9 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -36,6 +36,18 @@ public function setUp() ->getMock(); } + public function testRequestEventWillNotBeEmittedForIncompleteHeaders() + { + $server = new Server($this->socket); + $server->on('request', $this->expectCallableNever()); + + $this->socket->emit('connection', array($this->connection)); + + $data = ''; + $data .= "GET / HTTP/1.1\r\n"; + $this->connection->emit('data', array($data)); + } + public function testRequestEventIsEmitted() { $server = new Server($this->socket); @@ -107,6 +119,62 @@ public function testRequestResumeWillbeForwardedToConnection() $this->connection->emit('data', array($data)); } + public function testRequestEventWithoutBodyWillNotEmitData() + { + $never = $this->expectCallableNever(); + + $server = new Server($this->socket); + $server->on('request', function (Request $request) use ($never) { + $request->on('data', $never); + }); + + $this->socket->emit('connection', array($this->connection)); + + $data = $this->createGetRequest(); + $this->connection->emit('data', array($data)); + } + + public function testRequestEventWithSecondDataEventWillEmitBodyData() + { + $once = $this->expectCallableOnceWith('incomplete'); + + $server = new Server($this->socket); + $server->on('request', function (Request $request) use ($once) { + $request->on('data', $once); + }); + + $this->socket->emit('connection', array($this->connection)); + + $data = ''; + $data .= "POST / HTTP/1.1\r\n"; + $data .= "Content-Length: 100\r\n"; + $data .= "\r\n"; + $data .= "incomplete"; + $this->connection->emit('data', array($data)); + } + + public function testRequestEventWithPartialBodyWillEmitData() + { + $once = $this->expectCallableOnceWith('incomplete'); + + $server = new Server($this->socket); + $server->on('request', function (Request $request) use ($once) { + $request->on('data', $once); + }); + + $this->socket->emit('connection', array($this->connection)); + + $data = ''; + $data .= "POST / HTTP/1.1\r\n"; + $data .= "Content-Length: 100\r\n"; + $data .= "\r\n"; + $this->connection->emit('data', array($data)); + + $data = ''; + $data .= "incomplete"; + $this->connection->emit('data', array($data)); + } + public function testResponseContainsPoweredByHeader() { $server = new Server($this->socket); diff --git a/tests/TestCase.php b/tests/TestCase.php index 24fe27f2..73bb401e 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -24,6 +24,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();