Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] Adds new RequestSent and ResponseReceived events to the HTTP Client #37572

Merged
merged 9 commits into from
Jun 3, 2021
26 changes: 26 additions & 0 deletions src/Illuminate/Http/Client/Events/RequestSending.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Illuminate\Http\Client\Events;

use Illuminate\Http\Client\Request;

class RequestSending
{
/**
* The request instance.
*
* @var \Illuminate\Http\Client\Request
*/
public $request;

/**
* Create a new event instance.
*
* @param \Illuminate\Http\Client\Request $request
* @return void
*/
public function __construct(Request $request)
{
$this->request = $request;
}
}
36 changes: 36 additions & 0 deletions src/Illuminate/Http/Client/Events/ResponseReceived.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Illuminate\Http\Client\Events;

use Illuminate\Http\Client\Request;
use Illuminate\Http\Client\Response;

class ResponseReceived
{
/**
* The request instance.
*
* @var \Illuminate\Http\Client\Request
*/
public $request;

/**
* The response instance.
*
* @var \Illuminate\Http\Client\Response
*/
public $response;

/**
* Create a new event instance.
*
* @param \Illuminate\Http\Client\Request $request
* @param \Illuminate\Http\Client\Response $response
* @return void
*/
public function __construct(Request $request, Response $response)
{
$this->request = $request;
$this->response = $response;
}
}
23 changes: 22 additions & 1 deletion src/Illuminate/Http/Client/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Closure;
use GuzzleHttp\Psr7\Response as Psr7Response;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
use PHPUnit\Framework\Assert as PHPUnit;
Expand Down Expand Up @@ -54,6 +55,13 @@ class Factory
__call as macroCall;
}

/**
* The event dispatcher implementation.
*
* @var \Illuminate\Contracts\Events\Dispatcher|null
*/
protected $dispatcher;

/**
* The stub callables that will handle requests.
*
Expand Down Expand Up @@ -85,10 +93,13 @@ class Factory
/**
* Create a new factory instance.
*
* @param \Illuminate\Contracts\Events\Dispatcher|null $dispatcher
* @return void
*/
public function __construct()
public function __construct(Dispatcher $dispatcher = null)
{
$this->dispatcher = $dispatcher;

$this->stubCallbacks = collect();
}

Expand Down Expand Up @@ -340,6 +351,16 @@ protected function newPendingRequest()
return new PendingRequest($this);
}

/**
* Get the current event dispatcher implementation.
*
* @return \Illuminate\Contracts\Events\Dispatcher|null
*/
public function getDispatcher()
{
return $this->dispatcher;
}

/**
* Execute a method against a new pending request instance.
*
Expand Down
39 changes: 39 additions & 0 deletions src/Illuminate/Http/Client/PendingRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\TransferException;
use GuzzleHttp\HandlerStack;
use Illuminate\Http\Client\Events\RequestSending;
use Illuminate\Http\Client\Events\ResponseReceived;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
Expand Down Expand Up @@ -130,6 +132,13 @@ class PendingRequest
*/
protected $promise;

/**
* The sent request object, if a request has been made.
*
* @var \Illuminate\Http\Client\Request|null
*/
protected $request;

/**
* Create a new HTTP Client instance.
*
Expand All @@ -148,7 +157,10 @@ public function __construct(Factory $factory = null)
];

$this->beforeSendingCallbacks = collect([function (Request $request, array $options) {
$this->request = $request;
$this->cookies = $options['cookies'];

$this->dispatchRequestSendingEvent();
}]);
}

Expand Down Expand Up @@ -660,6 +672,8 @@ public function send(string $method, string $url, array $options = [])
if ($this->tries > 1 && ! $response->successful()) {
$response->throw();
}

$this->dispatchResponseReceivedEvent($response);
});
} catch (ConnectException $e) {
throw new ConnectionException($e->getMessage(), 0, $e);
Expand Down Expand Up @@ -951,6 +965,31 @@ public function getPromise()
return $this->promise;
}

/**
* Dispatch the RequestSending event if a dispatcher is available.
*
* @return void
*/
protected function dispatchRequestSendingEvent()
{
if ($dispatcher = optional($this->factory)->getDispatcher()) {
$dispatcher->dispatch(new RequestSending($this->request));
}
}

/**
* Dispatch the ResponseReceived event if a dispatcher is available.
*
* @param \Illuminate\Http\Client\Response $response
* @return void
*/
protected function dispatchResponseReceivedEvent(Response $response)
{
if ($dispatcher = optional($this->factory)->getDispatcher()) {
$dispatcher->dispatch(new ResponseReceived($this->request, $response));
}
}

/**
* Set the client instance.
*
Expand Down
22 changes: 22 additions & 0 deletions tests/Http/HttpClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Psr7\Response as Psr7Response;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Http\Client\Events\RequestSending;
use Illuminate\Http\Client\Events\ResponseReceived;
use Illuminate\Http\Client\Factory;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\Pool;
Expand All @@ -13,6 +16,7 @@
use Illuminate\Http\Client\ResponseSequence;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Mockery as m;
use OutOfBoundsException;
use PHPUnit\Framework\AssertionFailedError;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -917,4 +921,22 @@ public function testMultipleRequestsAreSentInThePoolWithKeys()
$this->assertSame(400, $responses['test400']->status());
$this->assertSame(500, $responses['test500']->status());
}

public function testTheRequestSendingAndResponseReceivedEventsAreFiredWhenARequestIsSent()
{
$events = m::mock(Dispatcher::class);
$events->shouldReceive('dispatch')->times(5)->with(m::type(RequestSending::class));
$events->shouldReceive('dispatch')->times(5)->with(m::type(ResponseReceived::class));

$factory = new Factory($events);
$factory->fake();

$factory->get('https://example.com');
$factory->head('https://example.com');
$factory->post('https://example.com');
$factory->patch('https://example.com');
$factory->delete('https://example.com');

m::close();
}
}