]> BookStack Code Mirror - bookstack/blobdiff - app/Actions/DispatchWebhookJob.php
Fixed failing webhook test cases
[bookstack] / app / Actions / DispatchWebhookJob.php
index 4cc749af3b782d50186ef8da5223ae891a5afce7..8f78150a991c84bf243e8e3969e753a7f120d776 100644 (file)
@@ -4,22 +4,25 @@ namespace BookStack\Actions;
 
 use BookStack\Auth\User;
 use BookStack\Entities\Models\Entity;
+use BookStack\Facades\Theme;
 use BookStack\Interfaces\Loggable;
 use BookStack\Model;
-use GuzzleHttp\Client;
-use GuzzleHttp\Psr7\Request;
+use BookStack\Theming\ThemeEvents;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Foundation\Bus\Dispatchable;
 use Illuminate\Queue\InteractsWithQueue;
 use Illuminate\Queue\SerializesModels;
 use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\Http;
 use Illuminate\Support\Facades\Log;
-use Psr\Http\Client\ClientExceptionInterface;
 
 class DispatchWebhookJob implements ShouldQueue
 {
-    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+    use Dispatchable;
+    use InteractsWithQueue;
+    use Queueable;
+    use SerializesModels;
 
     /**
      * @var Webhook
@@ -67,23 +70,32 @@ class DispatchWebhookJob implements ShouldQueue
      */
     public function handle()
     {
-        $httpClient = new Client([
-            'timeout' => 3,
-            'allow_redirects' => ['strict' => true],
-        ]);
-
-        $request = new Request('POST', $this->webhook->endpoint, [
-            'Content-Type' => 'application/json'
-        ], json_encode($this->buildWebhookData()));
+        $themeResponse = Theme::dispatch(ThemeEvents::WEBHOOK_CALL_BEFORE, $this->event, $this->webhook, $this->detail);
+        $webhookData = $themeResponse ?? $this->buildWebhookData();
+        $lastError = null;
 
         try {
-            $response = $httpClient->send($request);
-            if ($response->getStatusCode() >= 400) {
-                Log::error("Webhook call to endpoint {$this->webhook->endpoint} failed with status {$response->getStatusCode()}");
-            }
-        } catch (ClientExceptionInterface $exception) {
-            Log::error("Received error during webhook call to endpoint {$this->webhook->endpoint}: {$exception->getMessage()}");
+            $response = Http::asJson()
+                ->withOptions(['allow_redirects' => ['strict' => true]])
+                ->timeout($this->webhook->timeout)
+                ->post($this->webhook->endpoint, $webhookData);
+        } catch (\Exception $exception) {
+            $lastError = $exception->getMessage();
+            Log::error("Webhook call to endpoint {$this->webhook->endpoint} failed with error \"{$lastError}\"");
+        }
+
+        if (isset($response) && $response->failed()) {
+            $lastError = "Response status from endpoint was {$response->status()}";
+            Log::error("Webhook call to endpoint {$this->webhook->endpoint} failed with status {$response->status()}");
         }
+
+        $this->webhook->last_called_at = now();
+        if ($lastError) {
+            $this->webhook->last_errored_at = now();
+            $this->webhook->last_error = $lastError;
+        }
+
+        $this->webhook->save();
     }
 
     protected function buildWebhookData(): array
@@ -97,14 +109,14 @@ class DispatchWebhookJob implements ShouldQueue
             $textParts[] = '"' . $this->detail->name . '"';
         }
 
-        $data =  [
-            'event' => $this->event,
-            'text' => implode(' ', $textParts),
-            'triggered_at' => Carbon::createFromTimestampUTC($this->initiatedTime)->toISOString(),
-            'triggered_by' => $this->initiator->attributesToArray(),
+        $data = [
+            'event'                    => $this->event,
+            'text'                     => implode(' ', $textParts),
+            'triggered_at'             => Carbon::createFromTimestampUTC($this->initiatedTime)->toISOString(),
+            'triggered_by'             => $this->initiator->attributesToArray(),
             'triggered_by_profile_url' => $this->initiator->getProfileUrl(),
-            'webhook_id' => $this->webhook->id,
-            'webhook_name' => $this->webhook->name,
+            'webhook_id'               => $this->webhook->id,
+            'webhook_name'             => $this->webhook->name,
         ];
 
         if (method_exists($this->detail, 'getUrl')) {