Skip to content

No access to the guzzle client when middleware needs to be added #43

@linaori

Description

@linaori

When something isn't working as expected with Sendcloud, their support usually asks us for the JSON we send over. It seems the only way to add logging middleware is to extend the client and then override the constructor. This feels dangerous as it's easy to break something when the parent constructor changes. Based on a logger being passed around or not we will log the request/response. This is mostly a temporary solution that we can enable run-time for our tenants.

My feature request is something where I can get logging to work. This could be one of many forms:

  1. Logging added in the package itself, meaning we can pass a logger and not have to think about how it logs. This is the easiest solution from the perspective of the consumer of this package.
  2. The ability to pass specific guzzle options to the client. This is probably the easiest to implement, but also exposes the internal guzzle implementation and might not be ideal.
  3. Decouple from guzzle and rely on "PSR-7: HTTP message interfaces" instead, with guzzle being an optional dependency and if installed, the default implementation unless configured otherwise. This would be really nice as I could use the Symfony http client, but might not be worth the effort for you as maintainer.

Here's my current workaround to log the request/response. The reason I still call the parent constructor is so we can disable the alternative behavior completely by not passing the logger, this is coupled with a setting in our user interface so we can enable/disable logging whenever we want.

class ClientOverride extends Client
{
    public function __construct(
        protected string $publicKey,
        protected string $secretKey,
        protected string|null $partnerId = null,
        string|null $apiBaseUrl = null,
        LoggerInterface|null $logger = null,
    ) {
        parent::__construct($publicKey, $secretKey, $partnerId, $apiBaseUrl);

        if ($logger === null) {
            return;
        }

        $stack = HandlerStack::create();
        $stack->push(Middleware::log($logger, new MessageFormatter('{req_body} - {res_body}')));

        $clientConfig = [
            'base_uri' => $apiBaseUrl ?: self::API_BASE_URL,
            'timeout' => 60, // Mainly because the shipping methods endpoint can take a very long time to respond.
            'auth' => [
                $publicKey,
                $secretKey,
            ],
            'headers' => [
                'User-Agent' => 'jouwweb/sendcloud ' . Utils::defaultUserAgent(),
            ],
            'handler' => $stack,
        ];

        if ($this->partnerId) {
            $clientConfig['headers']['Sendcloud-Partner-Id'] = $this->partnerId;
        }

        $this->guzzleClient = new \GuzzleHttp\Client($clientConfig);
    }
}

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions