Skip to content

Commit 6f191e0

Browse files
committed
Consistent close() and error event semantics
1 parent 6af7139 commit 6f191e0

4 files changed

Lines changed: 35 additions & 24 deletions

File tree

README.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,32 @@ Calling this method finalizes the outgoing request body (which may be empty).
2222
Data will be buffered until the underlying connection is established, at which
2323
point buffered data will be sent and all further data will be ignored.
2424

25+
The `Request#close()` method can be used to
26+
forefully close sending the request.
27+
Unlike the `end()` method, this method discards any buffers and closes the
28+
underlying connection.
29+
2530
Request implements WritableStreamInterface, so a Stream can be piped to it.
2631
Interesting events emitted by Request:
2732

2833
* `response`: The response headers were received from the server and successfully
2934
parsed. The first argument is a Response instance.
3035
* `drain`: The outgoing buffer drained and the response is ready to accept more
3136
data for the next `write()` call.
32-
* `error`: An error occurred.
33-
* `end`: The request is finished. If an error occurred, it is passed as first
34-
argument. Second and third arguments are the Response and the Request.
37+
* `error`: An error occurred, an `Exception` is passed as first argument.
38+
* `close`: The request is closed. If an error occurred, this event will be
39+
preceeded by an `error` event.
3540

3641
Response implements ReadableStreamInterface.
3742
Interesting events emitted by Response:
3843

39-
* `data`: Passes a chunk of the response body as first argument and a Response
40-
object itself as second argument. When a response encounters a chunked encoded response it will parse it transparently for the user of `Response` and removing the `Transfer-Encoding` header.
41-
* `error`: An error occurred.
42-
* `end`: The response has been fully received. If an error
43-
occurred, it is passed as first argument.
44+
* `data`: Passes a chunk of the response body as first argument.
45+
When a response encounters a chunked encoded response it will parse it
46+
transparently for the user and removing the `Transfer-Encoding` header.
47+
* `error`: An error occurred, an `Exception` is passed as first argument.
48+
* `end`: The response has been fully received.
49+
* `close`: The response is closed. If an error occured, this event will be
50+
preceeded by an `error` event.
4451

4552
### Example
4653

src/Request.php

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ class Request implements WritableStreamInterface
2929
private $stream;
3030
private $buffer;
3131
private $responseFactory;
32-
private $response;
3332
private $state = self::STATE_INIT;
3433
private $ended = false;
3534

@@ -127,6 +126,7 @@ public function handleDrain()
127126
$this->emit('drain');
128127
}
129128

129+
/** @internal */
130130
public function handleData($data)
131131
{
132132
$this->buffer .= $data;
@@ -135,7 +135,7 @@ public function handleData($data)
135135
try {
136136
list($response, $bodyChunk) = $this->parseResponse($this->buffer);
137137
} catch (\InvalidArgumentException $exception) {
138-
$this->emit('error', [$exception, $this]);
138+
$this->emit('error', array($exception));
139139
}
140140

141141
$this->buffer = null;
@@ -150,8 +150,6 @@ public function handleData($data)
150150
return;
151151
}
152152

153-
$this->response = $response;
154-
155153
$response->on('close', function () {
156154
$this->close();
157155
});
@@ -169,12 +167,16 @@ public function handleData($data)
169167
}
170168
}
171169

170+
/** @internal */
172171
public function handleEnd()
173172
{
174-
$this->handleClose();
173+
$this->closeError(new \RuntimeException(
174+
"Connection ended before receiving response"
175+
));
175176
}
176177

177-
public function handleError($error)
178+
/** @internal */
179+
public function handleError(\Exception $error)
178180
{
179181
$this->closeError(new \RuntimeException(
180182
"An error occurred in the underlying stream",
@@ -183,13 +185,13 @@ public function handleError($error)
183185
));
184186
}
185187

188+
/** @internal */
186189
public function handleClose()
187190
{
188-
$this->closeError(new \RuntimeException(
189-
"Connection closed before receiving response"
190-
));
191+
$this->close();
191192
}
192193

194+
/** @internal */
193195
public function closeError(\Exception $error)
194196
{
195197
if (self::STATE_END <= $this->state) {
@@ -212,7 +214,7 @@ public function close()
212214
$this->stream->close();
213215
}
214216

215-
$this->emit('close', array());
217+
$this->emit('close');
216218
$this->removeAllListeners();
217219
}
218220

src/Response.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,25 @@ public function getHeaders()
7575
return $this->headers;
7676
}
7777

78+
/** @internal */
7879
public function handleData($data)
7980
{
8081
if ($this->readable) {
8182
$this->emit('data', array($data));
8283
}
8384
}
8485

86+
/** @internal */
8587
public function handleEnd()
8688
{
8789
if (!$this->readable) {
8890
return;
8991
}
90-
$this->emit('end', array());
92+
$this->emit('end');
9193
$this->close();
9294
}
9395

96+
/** @internal */
9497
public function handleError(\Exception $error)
9598
{
9699
if (!$this->readable) {
@@ -105,6 +108,7 @@ public function handleError(\Exception $error)
105108
$this->close();
106109
}
107110

111+
/** @internal */
108112
public function handleClose()
109113
{
110114
$this->close();
@@ -117,11 +121,10 @@ public function close()
117121
}
118122

119123
$this->readable = false;
124+
$this->stream->close();
120125

121-
$this->emit('close', array());
122-
126+
$this->emit('close');
123127
$this->removeAllListeners();
124-
$this->stream->close();
125128
}
126129

127130
public function isReadable()

tests/RequestTest.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,7 @@ public function requestShouldEmitErrorIfGuzzleParseThrowsException()
216216
$handler->expects($this->once())
217217
->method('__invoke')
218218
->with(
219-
$this->isInstanceOf('\InvalidArgumentException'),
220-
$this->isInstanceOf('React\HttpClient\Request')
219+
$this->isInstanceOf('\InvalidArgumentException')
221220
);
222221

223222
$request->on('error', $handler);

0 commit comments

Comments
 (0)