Skip to content

Commit 10c51c1

Browse files
committed
Refactor: Sanitize payloads optionally in Senders instead of Report
- Added shared sanitization behaviour into an AbstractSender class - Injected the PayloadSanitizer here - Optionally call it in the prepare payload method when configured - Used the existing config array to take in the option - added the logic from ReportSanitizer into JsonEncodableSanitizer - Bound the sanitizer in the container
1 parent c756600 commit 10c51c1

File tree

13 files changed

+278
-184
lines changed

13 files changed

+278
-184
lines changed

shared/FakeSender.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
use Closure;
66
use Spatie\FlareClient\Enums\FlarePayloadType;
7-
use Spatie\FlareClient\Senders\Sender;
7+
use Spatie\FlareClient\Senders\AbstractSender;
88
use Spatie\FlareClient\Senders\Support\Response;
99

10-
class FakeSender implements Sender
10+
class FakeSender extends AbstractSender
1111
{
1212
/** @var array<int, array{verb: string, fullUrl: string, headers: array<string, string>, arguments: array<string, mixed>}> */
1313
public static array $requests = [];
@@ -33,7 +33,7 @@ public function post(
3333
'verb' => 'POST',
3434
'fullUrl' => $endpoint,
3535
'headers' => ['X-API-KEY' => $apiToken],
36-
'arguments' => $payload,
36+
'arguments' => $this->preparePayloadForEncoding($payload),
3737
];
3838

3939
$callback(new Response(200, []));

src/FlareProvider.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
use Spatie\FlareClient\Sampling\NeverSampler;
1818
use Spatie\FlareClient\Sampling\Sampler;
1919
use Spatie\FlareClient\Scopes\Scope;
20+
use Spatie\FlareClient\Senders\PayloadSanitizer;
2021
use Spatie\FlareClient\Senders\Sender;
22+
use Spatie\FlareClient\Senders\Support\JsonEncodableSanitizer;
2123
use Spatie\FlareClient\Support\BackTracer;
2224
use Spatie\FlareClient\Support\Container;
2325
use Spatie\FlareClient\Support\GracefulSpanEnder;
@@ -48,9 +50,15 @@ public function register(): void
4850
{
4951
$this->container ??= Container::instance();
5052

51-
$this->container->singleton(Sender::class, fn () => new $this->config->sender(
52-
$this->config->senderConfig
53-
));
53+
$this->container->singleton(PayloadSanitizer::class, fn () => new JsonEncodableSanitizer);
54+
55+
$this->container->singleton(
56+
Sender::class,
57+
fn () => new $this->config->sender(
58+
config:$this->config->senderConfig,
59+
sanitizer: $this->container->get(PayloadSanitizer::class)
60+
)
61+
);
5462

5563
$this->container->singleton(Api::class, fn () => new Api(
5664
apiToken: $this->config->apiToken ?? 'No Api Token provided',

src/Report.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use Spatie\FlareClient\Contracts\FlareSpanEventType;
66
use Spatie\FlareClient\Contracts\FlareSpanType;
77
use Spatie\FlareClient\Enums\OverriddenGrouping;
8-
use Spatie\FlareClient\Support\ReportSanitizer;
98

109
class Report
1110
{
@@ -57,6 +56,6 @@ public function toArray(): array
5756
$report['level'] = $this->level;
5857
}
5958

60-
return ReportSanitizer::sanitizePayload($report);
59+
return $report;
6160
}
6261
}

src/Senders/AbstractSender.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Spatie\FlareClient\Senders;
4+
5+
use Spatie\FlareClient\Senders\Support\JsonEncodableSanitizer;
6+
7+
abstract class AbstractSender implements Sender
8+
{
9+
protected bool $shouldSanitizePayloads;
10+
11+
/**
12+
* @param array<string,mixed> $config
13+
*/
14+
public function __construct(
15+
protected array $config = [],
16+
protected readonly PayloadSanitizer $sanitizer = new JsonEncodableSanitizer
17+
) {
18+
$this->shouldSanitizePayloads = $this->config['sanitize_malformed_data'] ?? false;
19+
}
20+
21+
/**
22+
* Sanitizes the payload when applicable
23+
*
24+
* @template K of array-key
25+
*
26+
* @param array<K,mixed> $payload
27+
* @return array<K,mixed>
28+
*/
29+
protected function preparePayloadForEncoding(array $payload): array
30+
{
31+
if ($this->shouldSanitizePayloads) {
32+
return $this->sanitizer->sanitize($payload);
33+
}
34+
35+
return $payload;
36+
}
37+
}

src/Senders/CurlSender.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,22 @@
66
use CurlHandle;
77
use Spatie\FlareClient\Enums\FlarePayloadType;
88
use Spatie\FlareClient\Senders\Exceptions\ConnectionError;
9+
use Spatie\FlareClient\Senders\Support\JsonEncodableSanitizer;
910
use Spatie\FlareClient\Senders\Support\Response;
1011

11-
class CurlSender implements Sender
12+
class CurlSender extends AbstractSender
1213
{
1314
protected int $timeout;
1415

1516
/** @var array<int, mixed> */
1617
private array $curlOptions;
1718

1819
public function __construct(
19-
protected array $config = []
20+
array $config = [],
21+
PayloadSanitizer $sanitizer = new JsonEncodableSanitizer
2022
) {
23+
parent::__construct($config, $sanitizer);
24+
2125
$this->timeout = $this->config['timeout'] ?? 10;
2226
$this->curlOptions = $this->config['curl_options'] ?? [];
2327
}
@@ -36,7 +40,9 @@ public function post(string $endpoint, string $apiToken, array $payload, FlarePa
3640

3741
$curlHandle = $this->getCurlHandle($fullUrl, $headers);
3842

39-
$encoded = json_encode($payload);
43+
$encoded = json_encode(
44+
$this->preparePayloadForEncoding($payload)
45+
);
4046

4147
if (json_last_error() !== JSON_ERROR_NONE) {
4248
throw new ConnectionError('Invalid JSON payload provided');

src/Senders/GuzzleSender.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@
55
use Closure;
66
use GuzzleHttp\Client;
77
use Spatie\FlareClient\Enums\FlarePayloadType;
8+
use Spatie\FlareClient\Senders\Support\JsonEncodableSanitizer;
89
use Spatie\FlareClient\Senders\Support\Response;
910

10-
class GuzzleSender implements Sender
11+
class GuzzleSender extends AbstractSender
1112
{
1213
protected Client $client;
1314

1415
public function __construct(
15-
protected array $config = []
16+
array $config = [],
17+
PayloadSanitizer $sanitizer = new JsonEncodableSanitizer
1618
) {
19+
parent::__construct($config, $sanitizer);
1720
$this->client = new Client($config);
1821
}
1922

@@ -25,7 +28,7 @@ public function post(string $endpoint, string $apiToken, array $payload, FlarePa
2528
'Content-Type' => 'application/json',
2629
'x-api-token' => $apiToken,
2730
],
28-
'json' => $payload,
31+
'json' => $this->preparePayloadForEncoding($payload),
2932
]);
3033

3134
$callback(new Response(

src/Senders/NullSender.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use Spatie\FlareClient\Enums\FlarePayloadType;
77
use Spatie\FlareClient\Senders\Support\Response;
88

9-
class NullSender implements Sender
9+
class NullSender extends AbstractSender
1010
{
1111
public function post(string $endpoint, string $apiToken, array $payload, FlarePayloadType $type, Closure $callback): void
1212
{

src/Senders/PayloadSanitizer.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Spatie\FlareClient\Senders;
4+
5+
interface PayloadSanitizer
6+
{
7+
/**
8+
* @template K of array-key
9+
*
10+
* @param array<K,mixed> $payload
11+
* @return array<K,mixed>
12+
*/
13+
public function sanitize(array $payload): array;
14+
}

src/Senders/Sender.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
interface Sender
1010
{
1111
/**
12-
* @param Closure(Response): void $callback
12+
* @param Closure(Response): void $callback
1313
*/
1414
public function post(
1515
string $endpoint,
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace Spatie\FlareClient\Senders\Support;
4+
5+
use JsonException;
6+
use Spatie\FlareClient\Senders\PayloadSanitizer;
7+
8+
class JsonEncodableSanitizer implements PayloadSanitizer
9+
{
10+
/**
11+
* A prefix ensuing replaced values in sanitized payloads remain identifiable
12+
*/
13+
const SANITIZED_PAYLOAD_ENTRY_REPLACEMENT_PREFIX = 'Spatie/Flare';
14+
15+
public function sanitize(array $payload): array
16+
{
17+
foreach ($payload as $key => $value) {
18+
try {
19+
json_encode($payload[$key], JSON_THROW_ON_ERROR);
20+
} catch (JsonException $e) {
21+
if (is_array($value)) {
22+
$payload[$key] = $this->sanitize($payload[$key]);
23+
24+
continue;
25+
}
26+
27+
$payload[$key] = $this->formattedReplacementMessage($value, $e->getMessage());
28+
}
29+
30+
}
31+
32+
return $payload;
33+
}
34+
35+
protected function formattedReplacementMessage(mixed $value, string $errorMessage): string
36+
{
37+
$valueInfo = is_string($value) ? strlen($value).' bytes' : gettype($value);
38+
39+
return sprintf(
40+
'[%s Failed to encode]: %s - %s',
41+
static::SANITIZED_PAYLOAD_ENTRY_REPLACEMENT_PREFIX,
42+
$valueInfo,
43+
$errorMessage
44+
);
45+
}
46+
}

0 commit comments

Comments
 (0)