From 7c411e67ce2a438931fb5f03da025e2d5a99d45c Mon Sep 17 00:00:00 2001 From: Mustafa BALCI Date: Thu, 12 Sep 2024 17:31:56 +0300 Subject: [PATCH 1/4] Renamed $response to $responseClass for better clarity --- src/Traits/Responses/HasCustomResponses.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Traits/Responses/HasCustomResponses.php b/src/Traits/Responses/HasCustomResponses.php index 0100ab7f..66d18f25 100644 --- a/src/Traits/Responses/HasCustomResponses.php +++ b/src/Traits/Responses/HasCustomResponses.php @@ -7,13 +7,13 @@ trait HasCustomResponses { /** - * Specify a default response. + * Specify a default response class. * * When null or an empty string, the response on the sender will be used. * * @var class-string<\Saloon\Http\Response>|null */ - protected ?string $response = null; + protected ?string $responseClass = null; /** * Resolve the custom response class @@ -22,6 +22,6 @@ trait HasCustomResponses */ public function resolveResponseClass(): ?string { - return $this->response ?? null; + return $this->responseClass ?? null; } } From 234c15122491d6f8875eb00e9b0d648dd1bfd049 Mon Sep 17 00:00:00 2001 From: Mustafa BALCI Date: Thu, 26 Sep 2024 16:22:21 +0300 Subject: [PATCH 2/4] HasCustomResponses trait changed to HasResponseClass --- src/Http/Connector.php | 4 ++-- src/Http/Request.php | 4 ++-- .../{HasCustomResponses.php => HasResponseClass.php} | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/Traits/Responses/{HasCustomResponses.php => HasResponseClass.php} (95%) diff --git a/src/Http/Connector.php b/src/Http/Connector.php index 18b49c8d..a45b150b 100644 --- a/src/Http/Connector.php +++ b/src/Http/Connector.php @@ -14,7 +14,7 @@ use Saloon\Traits\Connector\SendsRequests; use Saloon\Traits\Auth\AuthenticatesRequests; use Saloon\Traits\RequestProperties\HasTries; -use Saloon\Traits\Responses\HasCustomResponses; +use Saloon\Traits\Responses\HasResponseClass; use Saloon\Traits\Request\CreatesDtoFromResponse; use Saloon\Traits\RequestProperties\HasRequestProperties; @@ -23,7 +23,7 @@ abstract class Connector use CreatesDtoFromResponse; use AuthenticatesRequests; use HasRequestProperties; - use HasCustomResponses; + use HasResponseClass; use ManagesExceptions; use HandlesPsrRequest; use HasMockClient; diff --git a/src/Http/Request.php b/src/Http/Request.php index 111c428b..cb551ee0 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -15,7 +15,7 @@ use Saloon\Traits\ManagesExceptions; use Saloon\Traits\Auth\AuthenticatesRequests; use Saloon\Traits\RequestProperties\HasTries; -use Saloon\Traits\Responses\HasCustomResponses; +use Saloon\Traits\Responses\HasResponseClass; use Saloon\Traits\Request\CreatesDtoFromResponse; use Saloon\Traits\RequestProperties\HasRequestProperties; @@ -24,7 +24,7 @@ abstract class Request use CreatesDtoFromResponse; use AuthenticatesRequests; use HasRequestProperties; - use HasCustomResponses; + use HasResponseClass; use ManagesExceptions; use HandlesPsrRequest; use HasMockClient; diff --git a/src/Traits/Responses/HasCustomResponses.php b/src/Traits/Responses/HasResponseClass.php similarity index 95% rename from src/Traits/Responses/HasCustomResponses.php rename to src/Traits/Responses/HasResponseClass.php index 66d18f25..0e0acbb4 100644 --- a/src/Traits/Responses/HasCustomResponses.php +++ b/src/Traits/Responses/HasResponseClass.php @@ -4,7 +4,7 @@ namespace Saloon\Traits\Responses; -trait HasCustomResponses +trait HasResponseClass { /** * Specify a default response class. From 60dce0f3769101f2b94a79c7305b27390a7492aa Mon Sep 17 00:00:00 2001 From: Mustafa BALCI Date: Fri, 15 Nov 2024 16:15:42 +0300 Subject: [PATCH 3/4] Add BatchRequest class for handling multiple requests --- src/Http/BatchRequest.php | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/Http/BatchRequest.php diff --git a/src/Http/BatchRequest.php b/src/Http/BatchRequest.php new file mode 100644 index 00000000..45002adb --- /dev/null +++ b/src/Http/BatchRequest.php @@ -0,0 +1,53 @@ +requests ??= new ArrayStore($this->defaultRequests()); + } + + /** + * Add a request dynamically. + * + * @param Request $request + * @return void + */ + public function addRequest(Request $request): void + { + $this->requests->add(uniqid('request_', true), $request); + } + + /** + * Get default requests. + * + * @return array + */ + protected function defaultRequests(): array + { + return []; + } + + /** + * Process the batch of responses. + * + * @param array $responses + * @return mixed + */ + abstract public function processResponses(array $responses): mixed; +} From 256828f66b8eead5e26ba2a8927ca9bb81019bb8 Mon Sep 17 00:00:00 2001 From: Mustafa BALCI Date: Fri, 15 Nov 2024 16:16:23 +0300 Subject: [PATCH 4/4] Enhance SendsRequests trait to support batch requests and asynchronous handling --- src/Traits/Connector/SendsRequests.php | 52 ++++++++++++++++++-------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/Traits/Connector/SendsRequests.php b/src/Traits/Connector/SendsRequests.php index d4fe36d9..17e6f206 100644 --- a/src/Traits/Connector/SendsRequests.php +++ b/src/Traits/Connector/SendsRequests.php @@ -4,17 +4,17 @@ namespace Saloon\Traits\Connector; +use GuzzleHttp\Promise\PromiseInterface; +use GuzzleHttp\Promise\Utils; use LogicException; +use Saloon\Exceptions\Request\FatalRequestException; +use Saloon\Exceptions\Request\RequestException; +use Saloon\Http\BatchRequest; +use Saloon\Http\Faking\MockClient; +use Saloon\Http\PendingRequest; use Saloon\Http\Pool; use Saloon\Http\Request; use Saloon\Http\Response; -use GuzzleHttp\Promise\Utils; -use GuzzleHttp\Promise\Promise; -use Saloon\Http\PendingRequest; -use Saloon\Http\Faking\MockClient; -use GuzzleHttp\Promise\PromiseInterface; -use Saloon\Exceptions\Request\RequestException; -use Saloon\Exceptions\Request\FatalRequestException; trait SendsRequests { @@ -29,7 +29,7 @@ trait SendsRequests public function send(Request $request, MockClient $mockClient = null, callable $handleRetry = null): Response { if (is_null($handleRetry)) { - $handleRetry = static fn (): bool => true; + $handleRetry = static fn(): bool => true; } $attempts = 0; @@ -93,7 +93,7 @@ public function send(Request $request, MockClient $mockClient = null, callable $ $exceptionResponse = $exception instanceof RequestException ? $exception->getResponse() : null; // If the exception is a FatalRequestException, we'll execute the fatal pipeline - if($exception instanceof FatalRequestException) { + if ($exception instanceof FatalRequestException) { $exception->getPendingRequest()->executeFatalPipeline($exception); } @@ -126,17 +126,37 @@ public function send(Request $request, MockClient $mockClient = null, callable $ /** * Send a request asynchronously */ - public function sendAsync(Request $request, MockClient $mockClient = null): PromiseInterface + public function sendAsync(Request|BatchRequest $request, MockClient $mockClient = null): PromiseInterface { - $sender = $this->sender(); - // We'll wrap the following logic in our own Promise which means we won't // build up our PendingRequest until the promise is actually being sent // this is great because our middleware will only run right before // the request is sent. - return Utils::task(function () use ($request, $mockClient, $sender) { - $pendingRequest = $this->createPendingRequest($request, $mockClient)->setAsynchronous(true); + if ($request instanceof Request) { + return $this->prepareAsyncRequest($request, $mockClient); + } + + $requests = array_map( + fn($singleRequest) => $this->prepareAsyncRequest($singleRequest, $mockClient), + $request->getRequests()->all() + ); + + return Utils::all($requests)->then(fn(array $responses) => $request->processResponses($responses)); + } + + /** + * Prepare an asynchronous task for sending the request. + * + * @param Request $request + * @param MockClient|null $mockClient + * @return PromiseInterface + */ + protected function prepareAsyncRequest(Request $request, MockClient $mockClient = null): PromiseInterface + { + return Utils::task(function () use ($request, $mockClient) { + $pendingRequest = $this->createPendingRequest($request, $mockClient) + ->setAsynchronous(true); // We need to check if the Pending Request contains a fake response. // If it does, then we will create the fake response. Otherwise, @@ -147,10 +167,10 @@ public function sendAsync(Request $request, MockClient $mockClient = null): Prom if ($pendingRequest->hasFakeResponse()) { $requestPromise = $this->createFakeResponse($pendingRequest); } else { - $requestPromise = $sender->sendAsync($pendingRequest); + $requestPromise = $this->sender()->sendAsync($pendingRequest); } - $requestPromise->then(fn (Response $response) => $pendingRequest->executeResponsePipeline($response)); + $requestPromise->then(fn(Response $response) => $pendingRequest->executeResponsePipeline($response)); return $requestPromise; });