nicklaw5 / twitch-api-php

A Twitch API client for PHP.
https://packagist.org/packages/nicklaw5/twitch-api-php
MIT License
116 stars 48 forks source link

Enable request logging via middleware #14

Closed echosa closed 5 years ago

echosa commented 6 years ago

I'm trying to get request logging via middleware working, as described here: https://michaelstivala.com/logging-guzzle-requests/

However, the logger I need to use is a service, normally retrieved as $container->get('logger');. I'm not sure how I can inject this middleware with that logging service into the handlerstack of Guzzle for this library. Is that possible?

nicklaw5 commented 6 years ago

At present, no it's not possible. However, to implement such a feature is not difficult to achieve. All you would need to do is extend the currently supported options to include the ability to pass through Guzzle configuration options. For example:

$handlerStack = \GuzzleHttp\HandlerStack::create();
$handlerStack->push(
    // Add your logger implementation here
    // See http://guzzle.readthedocs.io/en/latest/handlers-and-middleware.html#handlerstack
);

$options = [
    'client_id' => 'YOUR-CLIENT-ID',
    'guzzle-config' => [
        'handler' => $handlerStack,
    ],
];

$twitchApi = new \TwitchApi\TwitchApi($options);

In this library's constructor we would need to create a new property and provide it with an empty array as default:

// TwitchApi.php

/**
 * @var array
 */
protected $guzzleConfig;

public function __construct(array $options)
{
    if (!isset($options['client_id'])) {
        throw new ClientIdRequiredException();
    }

    $this->setClientId($options['client_id']);
    $this->setClientSecret(isset($options['client_secret']) ? $options['client_secret'] : null);
    $this->setRedirectUri(isset($options['redirect_uri']) ? $options['redirect_uri'] : null);
    $this->setApiVersion(isset($options['api_version']) ? $options['api_version'] : $this->getDefaultApiVersion());
    $this->setScope(isset($options['scope']) ? $options['scope'] : []);

    // Add the the new Guzzle config options (we would need to implement the setter)
    $this->setGuzzleConfig(isset($options['guzzle-config']) ? $options['guzzle-config'] : []);
}

Then we just need to merge those Guzzle configuration options with the current set when creating the Guzzle client. For example:

// TwitchRequest.php

protected function getNewHttpClient($method, $params, $accessToken = null)
{
    // Merge the provided config with the default Guzzle config
    $config = array_merge([
        'http_errors' => $this->getHttpErrors(),
        'base_uri' => $this->baseUri,
        'timeout' => $this->getTimeout(),
        'headers' => [
            'Client-ID' => $this->getClientId(),
            'Accept' => sprintf('application/vnd.twitchtv.v%d+json', $this->getApiVersion()),
            'User-Agent' => ($this->getUserAgent() !== null) ? $this->getUserAgent() : GuzzleHttp\default_user_agent(),
        ],
    ], $this->getGuzzleConfig()); // again we'd need to implement the getter

    if ($accessToken) {
        $config['headers']['Authorization'] = sprintf('OAuth %s', $accessToken);
    }

    if (!empty($params)) {
        $config[($method == self::GET_METHOD) ? 'query' : 'json'] = $params;
    }

    return new GuzzleHttp\Client($config);
}

Or something like that....

I don't have the capacity to implement this sort of thing myself at this time, but I'm happy to accept a PR if you wanted to take a stab at it.

echosa commented 6 years ago

I'll see if I can get it working, and if so, I'll pass a PR your way. Appreciated!

echosa commented 5 years ago

Closing. The newly introduced New Twitch API code allows for injecting and using custom Guzzle instances, so this can be done there. Additionally, I don't think there's much need to add this to the old API.