Implement webhook inspector
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\WebhookEndpoint;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class ConfigureWebhookEndpointAction
|
||||
{
|
||||
/**
|
||||
* @param array<string, string|array<int, string>> $headers
|
||||
*/
|
||||
public function handle(
|
||||
?User $user,
|
||||
WebhookEndpoint $endpoint,
|
||||
int $status,
|
||||
array $headers,
|
||||
string $body,
|
||||
): WebhookEndpoint {
|
||||
Gate::forUser($user)->authorize('update', $endpoint);
|
||||
|
||||
$maxResponseBodyBytes = (int) config('webhooks.max_response_body_bytes', 1024 * 1024);
|
||||
|
||||
if (strlen($body) > $maxResponseBodyBytes) {
|
||||
throw ValidationException::withMessages([
|
||||
'response_body' => "The response body may not exceed {$maxResponseBodyBytes} bytes.",
|
||||
]);
|
||||
}
|
||||
|
||||
Validator::make([
|
||||
'status' => $status,
|
||||
'body' => $body,
|
||||
], [
|
||||
'status' => ['integer', 'between:100,599'],
|
||||
'body' => ['string'],
|
||||
])->validate();
|
||||
|
||||
$this->validateHeaders($headers);
|
||||
|
||||
$endpoint->forceFill([
|
||||
'response_status' => $status,
|
||||
'response_headers' => $headers,
|
||||
'response_body' => $body,
|
||||
])->save();
|
||||
|
||||
return $endpoint->refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string|array<int, string>> $headers
|
||||
*/
|
||||
private function validateHeaders(array $headers): void
|
||||
{
|
||||
if (count($headers) > 50) {
|
||||
throw ValidationException::withMessages([
|
||||
'response_headers' => 'A maximum of 50 response headers is allowed.',
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($headers as $name => $value) {
|
||||
if (! is_string($name) || preg_match("/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/", $name) !== 1) {
|
||||
throw ValidationException::withMessages([
|
||||
'response_headers' => 'Every response header name must be a valid HTTP header name.',
|
||||
]);
|
||||
}
|
||||
|
||||
$values = is_array($value) ? $value : [$value];
|
||||
|
||||
foreach ($values as $headerValue) {
|
||||
if (! is_string($headerValue) || preg_match('/[\r\n]/', $headerValue) === 1 || strlen($headerValue) > 8192) {
|
||||
throw ValidationException::withMessages([
|
||||
'response_headers' => 'Response headers must not contain line breaks and may not exceed 8 KiB.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user