From 93761d9963e8bb23d821521b6ff26e06857bcaaf Mon Sep 17 00:00:00 2001 From: Vlad Shashkov Date: Mon, 15 Jun 2026 15:48:07 +0300 Subject: [PATCH 1/2] Added source for DaDataException --- .../Exception/BadRequestException.php | 7 ++- .../HttpClient/Exception/DaDataException.php | 15 +++++ .../Exception/ForbiddenException.php | 7 ++- .../InternalServerErrorException.php | 7 ++- .../Exception/NotFoundException.php | 7 ++- .../Exception/UnauthorizedException.php | 7 ++- .../Middleware/ClientErrorMiddleware.php | 10 ++-- .../Middleware/InternalServerMiddleware.php | 4 +- .../Middleware/SourceAwareMiddleware.php | 37 +++++++++++++ src/RestClientBuilder.php | 55 ++++++++++++++----- 10 files changed, 124 insertions(+), 32 deletions(-) create mode 100644 src/Infrastructure/HttpClient/Middleware/SourceAwareMiddleware.php diff --git a/src/Infrastructure/HttpClient/Exception/BadRequestException.php b/src/Infrastructure/HttpClient/Exception/BadRequestException.php index cf2381c..aaf947d 100644 --- a/src/Infrastructure/HttpClient/Exception/BadRequestException.php +++ b/src/Infrastructure/HttpClient/Exception/BadRequestException.php @@ -16,8 +16,11 @@ final class BadRequestException extends DaDataException { - public static function create(Response $response, Request $request): self + /** + * @param non-empty-string $source + */ + public static function create(Response $response, Request $request, string $source): self { - return new self($response, $request, 'Bad request'); + return new self($response, $request, $source, 'Bad request'); } } diff --git a/src/Infrastructure/HttpClient/Exception/DaDataException.php b/src/Infrastructure/HttpClient/Exception/DaDataException.php index 6039fa2..28cce05 100644 --- a/src/Infrastructure/HttpClient/Exception/DaDataException.php +++ b/src/Infrastructure/HttpClient/Exception/DaDataException.php @@ -21,19 +21,34 @@ abstract class DaDataException extends \Exception implements ClientException private Request $request; + /** + * @var non-empty-string + */ + private string $source; + final protected function __construct( Response $response, Request $request, + string $source, string $message = '', int $code = 0, ?\Throwable $previous = null ) { $this->response = $response; $this->request = $request; + $this->source = $source; parent::__construct($message, $code, $previous); } + /** + * @return non-empty-string + */ + final public function getSource(): string + { + return $this->source; + } + final public function getResponse(): Response { return $this->response; diff --git a/src/Infrastructure/HttpClient/Exception/ForbiddenException.php b/src/Infrastructure/HttpClient/Exception/ForbiddenException.php index 9829b66..caae5d0 100644 --- a/src/Infrastructure/HttpClient/Exception/ForbiddenException.php +++ b/src/Infrastructure/HttpClient/Exception/ForbiddenException.php @@ -16,8 +16,11 @@ final class ForbiddenException extends DaDataException { - public static function create(Response $response, Request $request): self + /** + * @param non-empty-string $source + */ + public static function create(Response $response, Request $request, string $source): self { - return new self($response, $request, 'Forbidden'); + return new self($response, $request, $source, 'Forbidden'); } } diff --git a/src/Infrastructure/HttpClient/Exception/InternalServerErrorException.php b/src/Infrastructure/HttpClient/Exception/InternalServerErrorException.php index 939b00e..6dddf35 100644 --- a/src/Infrastructure/HttpClient/Exception/InternalServerErrorException.php +++ b/src/Infrastructure/HttpClient/Exception/InternalServerErrorException.php @@ -16,8 +16,11 @@ final class InternalServerErrorException extends DaDataException { - public static function create(Response $response, Request $request): self + /** + * @param non-empty-string $source + */ + public static function create(Response $response, Request $request, string $source): self { - return new self($response, $request, 'Internal Server Error'); + return new self($response, $request, $source, 'Internal Server Error'); } } diff --git a/src/Infrastructure/HttpClient/Exception/NotFoundException.php b/src/Infrastructure/HttpClient/Exception/NotFoundException.php index 252d8b8..7433841 100644 --- a/src/Infrastructure/HttpClient/Exception/NotFoundException.php +++ b/src/Infrastructure/HttpClient/Exception/NotFoundException.php @@ -16,8 +16,11 @@ final class NotFoundException extends DaDataException { - public static function create(Response $response, Request $request): self + /** + * @param non-empty-string $source + */ + public static function create(Response $response, Request $request, string $source): self { - return new self($response, $request, 'Not Found'); + return new self($response, $request, $source, 'Not Found'); } } diff --git a/src/Infrastructure/HttpClient/Exception/UnauthorizedException.php b/src/Infrastructure/HttpClient/Exception/UnauthorizedException.php index 3b80b72..6c2532d 100644 --- a/src/Infrastructure/HttpClient/Exception/UnauthorizedException.php +++ b/src/Infrastructure/HttpClient/Exception/UnauthorizedException.php @@ -16,8 +16,11 @@ final class UnauthorizedException extends DaDataException { - public static function create(Response $response, Request $request): self + /** + * @param non-empty-string $source + */ + public static function create(Response $response, Request $request, string $source): self { - return new self($response, $request, 'Unauthorized'); + return new self($response, $request, $source, 'Unauthorized'); } } diff --git a/src/Infrastructure/HttpClient/Middleware/ClientErrorMiddleware.php b/src/Infrastructure/HttpClient/Middleware/ClientErrorMiddleware.php index 7273ba6..7801ac6 100644 --- a/src/Infrastructure/HttpClient/Middleware/ClientErrorMiddleware.php +++ b/src/Infrastructure/HttpClient/Middleware/ClientErrorMiddleware.php @@ -20,7 +20,7 @@ use Vanta\Integration\DaData\Infrastructure\HttpClient\Exception\UnauthorizedException; use Yiisoft\Http\Status; -final class ClientErrorMiddleware implements Middleware +final class ClientErrorMiddleware extends SourceAwareMiddleware { public function process(Request $request, ConfigurationClient $configuration, callable $next): Response { @@ -28,19 +28,19 @@ public function process(Request $request, ConfigurationClient $configuration, ca $statusCode = $response->getStatusCode(); if (Status::UNAUTHORIZED == $statusCode) { - throw UnauthorizedException::create($response, $request); + throw UnauthorizedException::create($response, $request, $this->source); } if (Status::FORBIDDEN == $statusCode) { - throw ForbiddenException::create($response, $request); + throw ForbiddenException::create($response, $request, $this->source); } if (Status::NOT_FOUND === $statusCode) { - throw NotFoundException::create($response, $request); + throw NotFoundException::create($response, $request, $this->source); } if ($statusCode >= Status::BAD_REQUEST && $statusCode <= Status::UNAVAILABLE_FOR_LEGAL_REASONS) { - throw BadRequestException::create($response, $request); + throw BadRequestException::create($response, $request, $this->source); } return $response; diff --git a/src/Infrastructure/HttpClient/Middleware/InternalServerMiddleware.php b/src/Infrastructure/HttpClient/Middleware/InternalServerMiddleware.php index e6133e0..c492579 100644 --- a/src/Infrastructure/HttpClient/Middleware/InternalServerMiddleware.php +++ b/src/Infrastructure/HttpClient/Middleware/InternalServerMiddleware.php @@ -17,7 +17,7 @@ use Vanta\Integration\DaData\Infrastructure\HttpClient\Exception\InternalServerErrorException; use Yiisoft\Http\Status; -final class InternalServerMiddleware implements Middleware +final class InternalServerMiddleware extends SourceAwareMiddleware { public function process(Request $request, ConfigurationClient $configuration, callable $next): Response { @@ -28,6 +28,6 @@ public function process(Request $request, ConfigurationClient $configuration, ca return $response; } - throw InternalServerErrorException::create($response, $request); + throw InternalServerErrorException::create($response, $request, $this->source); } } diff --git a/src/Infrastructure/HttpClient/Middleware/SourceAwareMiddleware.php b/src/Infrastructure/HttpClient/Middleware/SourceAwareMiddleware.php new file mode 100644 index 0000000..1ad3b8e --- /dev/null +++ b/src/Infrastructure/HttpClient/Middleware/SourceAwareMiddleware.php @@ -0,0 +1,37 @@ + + * @copyright Copyright (c) 2026, The Vanta + */ +declare(strict_types=1); + +namespace Vanta\Integration\DaData\Infrastructure\HttpClient\Middleware; + +abstract class SourceAwareMiddleware implements Middleware +{ + /** + * @var non-empty-string + */ + protected string $source; + + /** + * @param non-empty-string $source + */ + public function __construct(string $source = 'none') + { + $this->source = $source; + } + + /** + * @param non-empty-string $source + * + * @return static + */ + final public function withSource(string $source): self + { + return new static($source); + } +} diff --git a/src/RestClientBuilder.php b/src/RestClientBuilder.php index 9ecd6b2..e80edb8 100644 --- a/src/RestClientBuilder.php +++ b/src/RestClientBuilder.php @@ -37,6 +37,7 @@ use Vanta\Integration\DaData\Infrastructure\HttpClient\Middleware\InternalServerMiddleware; use Vanta\Integration\DaData\Infrastructure\HttpClient\Middleware\Middleware; use Vanta\Integration\DaData\Infrastructure\HttpClient\Middleware\PipelineMiddleware; +use Vanta\Integration\DaData\Infrastructure\HttpClient\Middleware\SourceAwareMiddleware; use Vanta\Integration\DaData\Infrastructure\HttpClient\Middleware\UrlMiddleware; use Vanta\Integration\DaData\Infrastructure\PropertyInfo\Extractor\PollyfillPhpStanExtractor; use Vanta\Integration\DaData\Infrastructure\Serializer\CapitalMarkerNormalizer; @@ -145,6 +146,20 @@ public static function create(PsrHttpClient $client, ?string $apiKey = null, ?st return new self($client, $serializer, $apiKey, $secretKey, $middlewares); } + /** + * @param non-empty-string $source + */ + private function withSource(string $source): self + { + return new self( + $this->client, + $this->serializer, + $this->apiKey, + $this->secretKey, + array_map(static fn (Middleware $m): Middleware => $m instanceof SourceAwareMiddleware ? $m->withSource($source) : $m, $this->middlewares), + ); + } + public function addMiddleware(Middleware $middleware): self { return new self( @@ -185,11 +200,13 @@ public function withClient(PsrHttpClient $client): self */ public function createCleanFullNameClient(string $url = 'https://cleaner.dadata.ru'): CleanFullNameClient { + $new = $this->withSource('CLEAN-FULLNAME-CLIENT'); + return new RestCleanFullNameClient( - $this->serializer, + $new->serializer, new HttpClient( - new ConfigurationClient($this->apiKey, $this->secretKey, $url), - new PipelineMiddleware($this->middlewares, $this->client) + new ConfigurationClient($new->apiKey, $new->secretKey, $url), + new PipelineMiddleware($new->middlewares, $new->client) ) ); } @@ -199,11 +216,13 @@ public function createCleanFullNameClient(string $url = 'https://cleaner.dadata. */ public function createSuggestAddressClient(string $url = 'https://suggestions.dadata.ru'): SuggestAddressClient { + $new = $this->withSource('SUGGEST-ADDRESSES-CLIENT'); + return new RestSuggestAddressClient( - $this->serializer, + $new->serializer, new HttpClient( - new ConfigurationClient($this->apiKey, $this->secretKey, $url), - new PipelineMiddleware($this->middlewares, $this->client) + new ConfigurationClient($new->apiKey, $new->secretKey, $url), + new PipelineMiddleware($new->middlewares, $new->client) ) ); } @@ -213,11 +232,13 @@ public function createSuggestAddressClient(string $url = 'https://suggestions.da */ public function createSuggestOrganizationClient(string $url = 'https://suggestions.dadata.ru'): SuggestOrganizationClient { + $new = $this->withSource('SUGGEST-ORGANIZATION-CLIENT'); + return new RestSuggestOrganizationClient( - $this->serializer, + $new->serializer, new HttpClient( - new ConfigurationClient($this->apiKey, $this->secretKey, $url), - new PipelineMiddleware($this->middlewares, $this->client) + new ConfigurationClient($new->apiKey, $new->secretKey, $url), + new PipelineMiddleware($new->middlewares, $new->client) ) ); } @@ -227,11 +248,13 @@ public function createSuggestOrganizationClient(string $url = 'https://suggestio */ public function createSuggestFullNameClient(string $url = 'https://suggestions.dadata.ru'): RestSuggestFullNameClient { + $new = $this->withSource('SUGGEST-FULLNAME-CLIENT'); + return new RestSuggestFullNameClient( - $this->serializer, + $new->serializer, new HttpClient( - new ConfigurationClient($this->apiKey, $this->secretKey, $url), - new PipelineMiddleware($this->middlewares, $this->client) + new ConfigurationClient($new->apiKey, $new->secretKey, $url), + new PipelineMiddleware($new->middlewares, $new->client) ) ); } @@ -241,11 +264,13 @@ public function createSuggestFullNameClient(string $url = 'https://suggestions.d */ public function createCleanAddressClient(string $url = 'https://cleaner.dadata.ru'): CleanAddressClient { + $new = $this->withSource('CLEAN-ADDRESSES-CLIENT'); + return new RestCleanAddressClient( - $this->serializer, + $new->serializer, new HttpClient( - new ConfigurationClient($this->apiKey, $this->secretKey, $url), - new PipelineMiddleware($this->middlewares, $this->client) + new ConfigurationClient($new->apiKey, $new->secretKey, $url), + new PipelineMiddleware($new->middlewares, $new->client) ) ); } From ff78ddc420ff9b7ba6671492792d4a514a84a63d Mon Sep 17 00:00:00 2001 From: Vlad Shashkov Date: Mon, 15 Jun 2026 15:55:11 +0300 Subject: [PATCH 2/2] Added source for DaDataException --- src/Infrastructure/HttpClient/Exception/DaDataException.php | 3 +++ .../HttpClient/Middleware/SourceAwareMiddleware.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/HttpClient/Exception/DaDataException.php b/src/Infrastructure/HttpClient/Exception/DaDataException.php index 28cce05..0eac396 100644 --- a/src/Infrastructure/HttpClient/Exception/DaDataException.php +++ b/src/Infrastructure/HttpClient/Exception/DaDataException.php @@ -26,6 +26,9 @@ abstract class DaDataException extends \Exception implements ClientException */ private string $source; + /** + * @param non-empty-string $source + */ final protected function __construct( Response $response, Request $request, diff --git a/src/Infrastructure/HttpClient/Middleware/SourceAwareMiddleware.php b/src/Infrastructure/HttpClient/Middleware/SourceAwareMiddleware.php index 1ad3b8e..b1cfb62 100644 --- a/src/Infrastructure/HttpClient/Middleware/SourceAwareMiddleware.php +++ b/src/Infrastructure/HttpClient/Middleware/SourceAwareMiddleware.php @@ -20,7 +20,7 @@ abstract class SourceAwareMiddleware implements Middleware /** * @param non-empty-string $source */ - public function __construct(string $source = 'none') + final public function __construct(string $source = 'none') { $this->source = $source; }