diff --git a/CHANGELOG.md b/CHANGELOG.md index e8baaa2d..18dbe530 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,9 @@ ### Added +- Option to configure default host for each client. default_host to add host if missing, force_host to change all requests to a specific host. - Support for BatchClient -- The stopwatch plugin in included by default when using profiling. +- The stopwatch plugin in included by default when using profiling. ### Changed diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index f6ef7e4f..1c73b29f 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -92,6 +92,7 @@ public function getConfigTreeBuilder() return $v; }) ->end() + ->fixXmlConfig('client') ->children() ->arrayNode('main_alias') ->addDefaultsIfNotSet() @@ -184,6 +185,22 @@ protected function configureClients(ArrayNodeDefinition $root) ->defaultFalse() ->info('Set to true to get the client wrapped in a BatchClient which allows you to send multiple request at the same time.') ->end() + ->arrayNode('options') + ->validate() + ->ifTrue(function ($options) { + return array_key_exists('default_host', $options) && array_key_exists('force_host', $options); + }) + ->thenInvalid('You can only set one of default_host and force_host for each client') + ->end() + ->children() + ->scalarNode('default_host') + ->info('Configure the AddHostPlugin for this client. Add host if request is only for a path.') + ->end() + ->scalarNode('force_host') + ->info('Configure the AddHostPlugin for this client. Send all requests to this host regardless of host in request.') + ->end() + ->end() + ->end() ->arrayNode('plugins') ->info('A list of service ids of plugins. The order is important.') ->prototype('scalar')->end() @@ -202,7 +219,7 @@ protected function configurePlugins(ArrayNodeDefinition $root) ->arrayNode('plugins') ->addDefaultsIfNotSet() ->children() - ->append($this->addAuthenticationPluiginNode()) + ->append($this->addAuthenticationPluginNode()) ->arrayNode('cache') ->canBeEnabled() @@ -313,7 +330,7 @@ protected function configurePlugins(ArrayNodeDefinition $root) * * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition */ - private function addAuthenticationPluiginNode() + private function addAuthenticationPluginNode() { $builder = new TreeBuilder(); $node = $builder->root('authentication'); diff --git a/DependencyInjection/HttplugExtension.php b/DependencyInjection/HttplugExtension.php index 0e3c5315..6e034a7d 100644 --- a/DependencyInjection/HttplugExtension.php +++ b/DependencyInjection/HttplugExtension.php @@ -5,6 +5,7 @@ use Http\Client\Common\BatchClient; use Http\Client\Common\FlexibleHttpClient; use Http\Client\Common\HttpMethodsClient; +use Http\Client\Common\Plugin\AddHostPlugin; use Http\Client\Common\Plugin\AuthenticationPlugin; use Http\Discovery\HttpAsyncClientDiscovery; use Http\Discovery\HttpClientDiscovery; @@ -14,6 +15,7 @@ use Http\Message\Authentication\BasicAuth; use Http\Message\Authentication\Bearer; use Http\Message\Authentication\Wsse; +use Psr\Http\Message\UriInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; @@ -215,6 +217,7 @@ private function configureClient(ContainerBuilder $container, $name, array $argu { $serviceId = 'httplug.client.'.$name; + $plugins = $arguments['plugins']; $pluginClientOptions = []; if ($profiling) { @@ -234,6 +237,42 @@ private function configureClient(ContainerBuilder $container, $name, array $argu $pluginClientOptions['debug_plugins'] = [new Reference($debugPluginServiceId)]; } + if (array_key_exists('options', $arguments)) { + foreach ($arguments['options'] as $option => $value) { + switch ($option) { + case 'default_host': + $uriService = $serviceId.'.default_host_uri'; + $addHostPlugin = $serviceId.'.default_host_plugin'; + $this->createUri($container, $uriService, $value); + $container + ->register($addHostPlugin, AddHostPlugin::class) + ->setPublic(false) + ->addArgument(new Reference($uriService)) + ; + // add to end of plugins list unless explicitly configured + if (!in_array($addHostPlugin, $plugins)) { + $plugins[] = $addHostPlugin; + } + break; + case 'force_host': + $uriService = $serviceId.'.force_host_uri'; + $addHostPlugin = $serviceId.'.force_host_plugin'; + $this->createUri($container, $uriService, $value); + $container + ->register($addHostPlugin, AddHostPlugin::class) + ->setPublic(false) + ->addArgument(new Reference($uriService)) + ->addArgument(['replace' => true]) + ; + // add to end of plugins list unless explicitly configured + if (!in_array($addHostPlugin, $plugins)) { + $plugins[] = $addHostPlugin; + } + break; + } + } + } + $container ->register($serviceId, DummyClient::class) ->setFactory([PluginClientFactory::class, 'createPluginClient']) @@ -242,7 +281,7 @@ private function configureClient(ContainerBuilder $container, $name, array $argu function ($id) { return new Reference($id); }, - $arguments['plugins'] + $plugins ) ) ->addArgument(new Reference($arguments['factory'])) @@ -282,6 +321,23 @@ function ($id) { } } + /** + * Create a URI object with the default URI factory. + * + * @param ContainerBuilder $container + * @param string $serviceId Name of the private service to create + * @param string $uri String representation of the URI + */ + private function createUri(ContainerBuilder $container, $serviceId, $uri) + { + $container + ->register($serviceId, UriInterface::class) + ->setPublic(false) + ->setFactory([new Reference('httplug.uri_factory'), 'createUri']) + ->addArgument($uri) + ; + } + /** * Make the user can select what client is used for auto discovery. If none is provided, a service will be created * by finding a client using auto discovery. diff --git a/Tests/Resources/Fixtures/config/full.php b/Tests/Resources/Fixtures/config/full.php index 0a8ab554..9180b3c7 100644 --- a/Tests/Resources/Fixtures/config/full.php +++ b/Tests/Resources/Fixtures/config/full.php @@ -13,6 +13,15 @@ 'uri_factory' => 'Http\Message\UriFactory\GuzzleUriFactory', 'stream_factory' => 'Http\Message\StreamFactory\GuzzleStreamFactory', ], + 'clients' => [ + 'test' => [ + 'factory' => 'httplug.factory.guzzle6', + 'http_methods_client' => true, + 'options' => [ + 'default_host' => 'http://localhost', + ], + ], + ], 'profiling' => [ 'enabled' => true, 'formatter' => 'my_toolbar_formatter', diff --git a/Tests/Resources/Fixtures/config/full.xml b/Tests/Resources/Fixtures/config/full.xml index e0ded54b..83764450 100644 --- a/Tests/Resources/Fixtures/config/full.xml +++ b/Tests/Resources/Fixtures/config/full.xml @@ -14,6 +14,9 @@ Http\Message\UriFactory\GuzzleUriFactory Http\Message\StreamFactory\GuzzleStreamFactory + + + diff --git a/Tests/Resources/Fixtures/config/full.yml b/Tests/Resources/Fixtures/config/full.yml index 72341e8e..d8e7ef7a 100644 --- a/Tests/Resources/Fixtures/config/full.yml +++ b/Tests/Resources/Fixtures/config/full.yml @@ -9,6 +9,12 @@ httplug: message_factory: Http\Message\MessageFactory\GuzzleMessageFactory uri_factory: Http\Message\UriFactory\GuzzleUriFactory stream_factory: Http\Message\StreamFactory\GuzzleStreamFactory + clients: + test: + factory: httplug.factory.guzzle6 + http_methods_client: true + options: + default_host: http://localhost profiling: enabled: true formatter: my_toolbar_formatter diff --git a/Tests/Unit/DependencyInjection/ConfigurationTest.php b/Tests/Unit/DependencyInjection/ConfigurationTest.php index df931ea3..1d72fd8e 100644 --- a/Tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/Tests/Unit/DependencyInjection/ConfigurationTest.php @@ -115,7 +115,19 @@ public function testSupportsAllConfigFormats() 'uri_factory' => 'Http\Message\UriFactory\GuzzleUriFactory', 'stream_factory' => 'Http\Message\StreamFactory\GuzzleStreamFactory', ], - 'clients' => [], + 'clients' => [ + 'test' => [ + 'factory' => 'httplug.factory.guzzle6', + 'http_methods_client' => true, + 'flexible_client' => false, + 'batch_client' => false, + 'options' => [ + 'default_host' => 'http://localhost', + ], + 'plugins' => [], + 'config' => [], + ], + ], 'profiling' => [ 'enabled' => true, 'formatter' => 'my_toolbar_formatter',