Replies: 3 comments
-
As a possible starting point, this is my custom CallWebhookJob that uses the Laravel HTTP Client instead of guzzle directly. Total sidenote, why is the dispatchEvent private in the base class? <?php
declare(strict_types=1);
namespace App\Services\WebhookServer;
use Exception;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\RequestException;
use GuzzleHttp\Psr7\Response as GuzzleResponse;
use Spatie\WebhookServer\Events\WebhookCallFailedEvent;
use Illuminate\Http\Client\Response as HttpClientResponse;
use Spatie\WebhookServer\Events\WebhookCallSucceededEvent;
use Spatie\WebhookServer\Events\FinalWebhookCallFailedEvent;
class CallWebhookJob extends \Spatie\WebhookServer\CallWebhookJob
{
public function handle(): void
{
$lastAttempt = $this->attempts() >= $this->tries;
try {
$request = Http::withHeaders($this->headers)
->timeout($this->requestTimeout)
->unless($this->verifySsl, fn(PendingRequest $request) => $request->withoutVerifying())
->when($this->proxy, fn(PendingRequest $request) => $request->withOptions(['proxy' => $this->proxy]));
$response = match (strtoupper($this->httpVerb)) {
'GET' => $request->get($this->webhookUrl, $this->payload),
'POST' => $request->post($this->webhookUrl, $this->payload),
'PUT' => $request->put($this->webhookUrl, $this->payload),
};
$this->transferStats = $response->transferStats;
$response->throw();
$this->response = $this->toGuzzleResponse($response);
if (!Str::startsWith($this->response->getStatusCode(), 2)) {
throw new Exception('Webhook call failed');
}
$this->dispatchEvent(WebhookCallSucceededEvent::class);
return;
} catch (Exception $exception) {
$this->errorType = get_class($exception);
$this->errorMessage = $exception->getMessage();
if ($exception instanceof RequestException) {
$this->response = $this->toGuzzleResponse($exception->response);
}
if (!$lastAttempt) {
/** @var \Spatie\WebhookServer\BackoffStrategy\BackoffStrategy $backoffStrategy */
$backoffStrategy = app($this->backoffStrategyClass);
$waitInSeconds = $backoffStrategy->waitInSecondsAfterAttempt($this->attempts());
$this->release($waitInSeconds);
}
$this->dispatchEvent(WebhookCallFailedEvent::class);
if ($lastAttempt || $this->shouldBeRemovedFromQueue()) {
$this->dispatchEvent(FinalWebhookCallFailedEvent::class);
$this->throwExceptionOnFailure ? $this->fail($exception) : $this->delete();
}
}
}
protected function toGuzzleResponse(HttpClientResponse $response): GuzzleResponse
{
$psrResponse = $response->toPsrResponse();
return new GuzzleResponse(
$psrResponse->getStatusCode(),
$psrResponse->getHeaders(),
$psrResponse->getBody(),
$psrResponse->getProtocolVersion(),
$psrResponse->getReasonPhrase()
);
}
private function dispatchEvent(string $eventClass): void
{
event(new $eventClass(
$this->httpVerb,
$this->webhookUrl,
$this->payload,
$this->headers,
$this->meta,
$this->tags,
$this->attempts(),
$this->response,
$this->errorType,
$this->errorMessage,
$this->uuid,
$this->transferStats
));
}
} |
Beta Was this translation helpful? Give feedback.
-
@hailwood thank you for that. I really find it very useful. I'm using here and I just added a PATCH http verb. |
Beta Was this translation helpful? Give feedback.
-
I'd accept a PR that moves this package from Guzzle to Laravel's HTTP client. Breaking changes are allowed (I'll tag a new major). |
Beta Was this translation helpful? Give feedback.
-
Using Laravel's built in HTTP client would provide a number of benefits including:
Http::preventStrayRequests();
Beta Was this translation helpful? Give feedback.
All reactions