8p / EightPointsGuzzleBundle

⛽️ Integrates Guzzle 6.x, a PHP HTTP Client, into Symfony
MIT License
440 stars 71 forks source link

Injecting middlewares into the handler #90

Closed renanbr closed 7 years ago

renanbr commented 7 years ago

I would like to inject custom middlewares through service configuration, and I didn't understand how to do it with this library, even reading https://github.com/8p/GuzzleBundle/issues/21, https://github.com/8p/GuzzleBundle/pull/22 and https://github.com/8p/GuzzleBundle/issues/79

Once I didn't understood how to do it, I've started thinking how this bundle could provide it. It's the first time I'm working with this library, so let me know if there is a proper/better way to achieve what I want ;)

Exemple of usage:

I've a service named app.my_custom_middleware that implements __invoke() and do some stuff with the request instance, then ...

guzzle:
    clients:
        api:
            base_url: "http://api.domain.tld"
            plugin:
                custom:
                    - "@app.my_custom_middleware"

... then GuzzleExtension::createHandler() would be able to load middleres from service container ...

class GuzzleExtension
{
    // ....

    protected function createHandler()
    {
        // ....

        if (isset($config['plugin'])){

            // ....

            if (isset($config['plugin']['custom']) {
                $names = (array) isset($config['plugin']['custom'];
                foreach ($names as $name) {
                    $expression = new Expression(sprintf('service("%s")', $name));
                    $handler->addMethodCall('push', [$expression]);
                }
            }
        }

        // ....
    }

    // ....
}

Does it make sense?

gregurco commented 7 years ago

@renanbr PR #129 resolves your problem. With new plugin system you will be able to create your small plugins and to inject logic into handler. That's small example how to do it:

<?php

namespace Acme\Bundle\AcmeBundle;

use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\HttpKernel\Bundle\Bundle;

class Extension extends Bundle implements EightPointsGuzzleBundlePlugin
{
    public function getPluginName(): string
    {
        return 'custom';
    }

    public function addConfiguration(ArrayNodeDefinition $pluginNode)
    {
        $pluginNode
            ->addDefaultsIfNotSet()
                ->children()
                ->scalarNode('service')->defaultNull()->end();
    }

    public function loadForClient(array $config, ContainerBuilder $container, string $clientName, Definition $handler)
    {
        if (isset($config['service']) && $config['service']) {
            // do manipulations with $handler
        }
    }

    public function load(array $configs, ContainerBuilder $container)
    {
        // No need to implement
    }
}