Skip to content

Commit 96c9332

Browse files
committed
feat: add ResponseReceiving and ResponseReceived events
1 parent 7b6f59f commit 96c9332

File tree

4 files changed

+198
-0
lines changed

4 files changed

+198
-0
lines changed

src/Downloader/Downloader.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515

1616
use RoachPHP\Events\RequestDropped;
1717
use RoachPHP\Events\RequestSending;
18+
use RoachPHP\Events\ResponseDropped;
19+
use RoachPHP\Events\ResponseReceived;
20+
use RoachPHP\Events\ResponseReceiving;
1821
use RoachPHP\Http\ClientInterface;
1922
use RoachPHP\Http\Request;
2023
use RoachPHP\Http\Response;
@@ -100,6 +103,19 @@ public function flush(?callable $callback = null): void
100103

101104
private function onResponseReceived(Response $response, ?callable $callback): void
102105
{
106+
$event = new ResponseReceiving($response);
107+
$this->eventDispatcher->dispatch($event, ResponseReceiving::NAME);
108+
$response = $event->response;
109+
110+
if ($response->wasDropped()) {
111+
$this->eventDispatcher->dispatch(
112+
new ResponseDropped($response),
113+
ResponseDropped::NAME,
114+
);
115+
116+
return;
117+
}
118+
103119
foreach ($this->middleware as $middleware) {
104120
$response = $middleware->handleResponse($response);
105121

@@ -108,6 +124,19 @@ private function onResponseReceived(Response $response, ?callable $callback): vo
108124
}
109125
}
110126

127+
$event = new ResponseReceived($response);
128+
$this->eventDispatcher->dispatch($event, ResponseReceived::NAME);
129+
$response = $event->response;
130+
131+
if ($response->wasDropped()) {
132+
$this->eventDispatcher->dispatch(
133+
new ResponseDropped($response),
134+
ResponseDropped::NAME,
135+
);
136+
137+
return;
138+
}
139+
111140
if (null !== $callback) {
112141
$callback($response);
113142
}

src/Events/ResponseReceived.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2023 Kai Sassnowski
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*
11+
* @see https://github.com/roach-php/roach
12+
*/
13+
14+
namespace RoachPHP\Events;
15+
16+
use RoachPHP\Http\Response;
17+
use Symfony\Contracts\EventDispatcher\Event;
18+
19+
final class ResponseReceived extends Event
20+
{
21+
public const NAME = 'response.processed';
22+
23+
public function __construct(public Response $response)
24+
{
25+
}
26+
}

src/Events/ResponseReceiving.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2023 Kai Sassnowski
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*
11+
* @see https://github.com/roach-php/roach
12+
*/
13+
14+
namespace RoachPHP\Events;
15+
16+
use RoachPHP\Http\Response;
17+
use Symfony\Contracts\EventDispatcher\Event;
18+
19+
final class ResponseReceiving extends Event
20+
{
21+
public const NAME = 'response.received';
22+
23+
public function __construct(public Response $response)
24+
{
25+
}
26+
}

tests/Downloader/DownloaderTest.php

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
use RoachPHP\Events\FakeDispatcher;
2020
use RoachPHP\Events\RequestDropped;
2121
use RoachPHP\Events\RequestSending;
22+
use RoachPHP\Events\ResponseDropped;
23+
use RoachPHP\Events\ResponseReceived;
24+
use RoachPHP\Events\ResponseReceiving;
2225
use RoachPHP\Http\FakeClient;
2326
use RoachPHP\Http\Request;
2427
use RoachPHP\Http\Response;
@@ -216,4 +219,118 @@ public function testDispatchesAnEventIfRequestWasDroppedByListener(): void
216219
static fn (RequestDropped $event) => $event->request->getUri() === $request->getUri(),
217220
);
218221
}
222+
223+
public function testDispatchEventWhenResponseWasReceived(): void
224+
{
225+
$request = $this->makeRequest();
226+
227+
$this->downloader->prepare($request);
228+
$this->dispatcher->assertNotDispatched(ResponseReceiving::NAME);
229+
230+
$this->downloader->flush();
231+
$this->dispatcher->assertDispatched(
232+
ResponseReceiving::NAME,
233+
static fn (ResponseReceiving $event) => $event->response->getRequest()->getUri() === $request->getUri(),
234+
);
235+
}
236+
237+
public function testDontPassResponseToMiddlewareIfDroppedByExtension(): void
238+
{
239+
$request = $this->makeRequest();
240+
$this->dispatcher->listen(ResponseReceiving::NAME, static function (ResponseReceiving $event): void {
241+
$event->response = $event->response->drop('::reason::');
242+
});
243+
$middleware = new FakeMiddleware();
244+
$this->downloader->withMiddleware($middleware);
245+
246+
$this->downloader->prepare($request);
247+
$this->downloader->flush();
248+
249+
$middleware->assertNoResponseHandled();
250+
}
251+
252+
public function testFireEventIfReceivedResponseWasDroppedByExtension(): void
253+
{
254+
$request = $this->makeRequest();
255+
$this->dispatcher->listen(ResponseReceiving::NAME, static function (ResponseReceiving $event): void {
256+
$event->response = $event->response->drop('::reason::');
257+
});
258+
259+
$this->downloader->prepare($request);
260+
$this->downloader->flush();
261+
262+
$this->dispatcher->assertDispatched(
263+
ResponseDropped::NAME,
264+
static fn (ResponseDropped $event) => $event->response->getRequest()->getUri() === $request->getUri(),
265+
);
266+
}
267+
268+
public function testDontCallParseCallbackIfRequestWasDroppedByExtension(): void
269+
{
270+
$called = false;
271+
$request = $this->makeRequest();
272+
$this->dispatcher->listen(ResponseReceiving::NAME, static function (ResponseReceiving $event): void {
273+
$event->response = $event->response->drop('::reason::');
274+
});
275+
276+
$this->downloader->prepare($request);
277+
$this->downloader->flush(static function () use (&$called): void {
278+
$called = true;
279+
});
280+
281+
self::assertFalse($called);
282+
}
283+
284+
public function testDispatchEventWhenResponseWasProcessedByMiddleware(): void
285+
{
286+
$request = $this->makeRequest();
287+
$middleware = new FakeMiddleware(
288+
responseHandler: function (Response $response) {
289+
$this->dispatcher->assertNotDispatched(ResponseReceived::NAME);
290+
291+
return $response;
292+
},
293+
);
294+
$this->downloader->withMiddleware($middleware);
295+
296+
$this->downloader->prepare($request);
297+
$this->downloader->flush();
298+
299+
$this->dispatcher->assertDispatched(
300+
ResponseReceived::NAME,
301+
static fn (ResponseReceived $event) => $event->response->getRequest()->getUri() === $request->getUri(),
302+
);
303+
}
304+
305+
public function testFireEventIfProcessedResponseWasDroppedByExtension(): void
306+
{
307+
$request = $this->makeRequest();
308+
$this->dispatcher->listen(ResponseReceived::NAME, static function (ResponseReceived $event): void {
309+
$event->response = $event->response->drop('::reason::');
310+
});
311+
312+
$this->downloader->prepare($request);
313+
$this->downloader->flush();
314+
315+
$this->dispatcher->assertDispatched(
316+
ResponseDropped::NAME,
317+
static fn (ResponseDropped $event) => $event->response->getRequest()->getUri() === $request->getUri(),
318+
);
319+
}
320+
321+
public function testDontCallParseCallbackIfProcessedResponseWasDroppedByExtension(): void
322+
{
323+
$called = false;
324+
$request = $this->makeRequest();
325+
$this->dispatcher->listen(ResponseReceived::NAME, static function (ResponseReceived $event): void {
326+
$event->response = $event->response->drop('::reason::');
327+
});
328+
329+
$this->downloader->prepare($request);
330+
$this->downloader->flush(static function () use (&$called): void {
331+
$called = true;
332+
});
333+
334+
self::assertFalse($called);
335+
}
219336
}

0 commit comments

Comments
 (0)