Skip to content

Commit 391e1e7

Browse files
committed
Merge pull request #33 from arnaud-lb/drain-event
Emit drain event when the request is ready to receive more data
2 parents f382515 + 4618230 commit 391e1e7

File tree

2 files changed

+74
-4
lines changed

2 files changed

+74
-4
lines changed

src/Request.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class Request implements WritableStreamInterface
3232
private $response;
3333
private $state = self::STATE_INIT;
3434

35+
private $pendingWrites = array();
36+
3537
public function __construct(ConnectorInterface $connector, RequestData $requestData)
3638
{
3739
$this->connector = $connector;
@@ -89,9 +91,17 @@ public function write($data)
8991
return $this->stream->write($data);
9092
}
9193

92-
$this->on('headers-written', function ($this) use ($data) {
93-
$this->write($data);
94-
});
94+
if (!count($this->pendingWrites)) {
95+
$this->on('headers-written', function ($this) {
96+
foreach ($this->pendingWrites as $pw) {
97+
$this->write($pw);
98+
}
99+
$this->pendingWrites = array();
100+
$this->emit('drain', array($this));
101+
});
102+
}
103+
104+
$this->pendingWrites[] = $data;
95105

96106
if (self::STATE_WRITING_HEAD > $this->state) {
97107
$this->writeHead();

tests/RequestTest.php

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use React\Stream\Stream;
88
use React\Promise\FulfilledPromise;
99
use React\Promise\RejectedPromise;
10+
use React\Promise;
11+
use React\Promise\Deferred;
1012

1113
class RequestTest extends TestCase
1214
{
@@ -288,6 +290,53 @@ public function writeWithAPostRequestShouldSendToTheStream()
288290
$request->handleData("\r\nbody");
289291
}
290292

293+
/** @test */
294+
public function writeWithAPostRequestShouldSendBodyAfterHeadersAndEmitDrainEvent()
295+
{
296+
$requestData = new RequestData('POST', 'http://www.example.com');
297+
$request = new Request($this->connector, $requestData);
298+
299+
$resolveConnection = $this->successfulAsyncConnectionMock();
300+
301+
$this->stream
302+
->expects($this->at(4))
303+
->method('write')
304+
->with($this->matchesRegularExpression("#^POST / HTTP/1\.0\r\nHost: www.example.com\r\nUser-Agent:.*\r\n\r\n$#"));
305+
$this->stream
306+
->expects($this->at(5))
307+
->method('write')
308+
->with($this->identicalTo("some"));
309+
$this->stream
310+
->expects($this->at(6))
311+
->method('write')
312+
->with($this->identicalTo("post"));
313+
$this->stream
314+
->expects($this->at(7))
315+
->method('write')
316+
->with($this->identicalTo("data"));
317+
318+
$factory = $this->createCallableMock();
319+
$factory->expects($this->once())
320+
->method('__invoke')
321+
->will($this->returnValue($this->response));
322+
323+
$request->setResponseFactory($factory);
324+
325+
$this->assertFalse($request->write("some"));
326+
$this->assertFalse($request->write("post"));
327+
328+
$request->once('drain', function () use ($request) {
329+
$request->write("data");
330+
$request->end();
331+
});
332+
333+
$resolveConnection();
334+
335+
$request->handleData("HTTP/1.0 200 OK\r\n");
336+
$request->handleData("Content-Type: text/plain\r\n");
337+
$request->handleData("\r\nbody");
338+
}
339+
291340
/** @test */
292341
public function pipeShouldPipeDataIntoTheRequestBody()
293342
{
@@ -387,11 +436,22 @@ public function requestShouldRelayErrorEventsFromResponse()
387436

388437
private function successfulConnectionMock()
389438
{
439+
call_user_func($this->successfulAsyncConnectionMock());
440+
}
441+
442+
private function successfulAsyncConnectionMock()
443+
{
444+
$deferred = new Deferred();
445+
390446
$this->connector
391447
->expects($this->once())
392448
->method('create')
393449
->with('www.example.com', 80)
394-
->will($this->returnValue(new FulfilledPromise($this->stream)));
450+
->will($this->returnValue($deferred->promise()));
451+
452+
return function () use ($deferred) {
453+
$deferred->resolve($this->stream);
454+
};
395455
}
396456

397457
private function rejectedConnectionMock()

0 commit comments

Comments
 (0)