Skip to content

Commit 8e3a96e

Browse files
committed
Merge pull request #16 from Nyholm/plugins
Plugins
2 parents ce31ab9 + 190d59b commit 8e3a96e

File tree

5 files changed

+110
-11
lines changed

5 files changed

+110
-11
lines changed

ClientFactory/PluginClientFactory.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Http\HttplugBundle\ClientFactory;
4+
5+
use Http\Client\Plugin\PluginClient;
6+
7+
/**
8+
* This factory creates a PluginClient.
9+
*
10+
* @author Tobias Nyholm <[email protected]>
11+
*/
12+
class PluginClientFactory
13+
{
14+
/**
15+
* @param array $plugins
16+
* @param ClientFactoryInterface $factory
17+
* @param array $config
18+
*
19+
* @return PluginClient
20+
*/
21+
static public function createPluginClient(array $plugins, ClientFactoryInterface $factory, array $config)
22+
{
23+
return new PluginClient($factory->createClient($config), $plugins);
24+
}
25+
}

DependencyInjection/Configuration.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ protected function configureClients(ArrayNodeDefinition $root)
9090
->cannotBeEmpty()
9191
->info('The service id of a factory to use when creating the adapter.')
9292
->end()
93+
->arrayNode('plugins')
94+
->info('A list of service ids of plugins. The order is important.')
95+
->prototype('scalar')->end()
96+
->end()
9397
->variableNode('config')->end()
9498
->end()
9599
->end();

DependencyInjection/HttplugExtension.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public function load(array $configs, ContainerBuilder $container)
2525
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
2626

2727
$loader->load('services.xml');
28+
$loader->load('plugins.xml');
2829
$loader->load('discovery.xml');
2930
foreach ($config['classes'] as $service => $class) {
3031
if (!empty($class)) {
@@ -36,19 +37,42 @@ public function load(array $configs, ContainerBuilder $container)
3637
foreach ($config['main_alias'] as $type => $id) {
3738
$container->setAlias(sprintf('httplug.%s', $type), $id);
3839
}
40+
$this->configureClients($container, $config);
3941

40-
// Configure client services
42+
43+
}
44+
45+
/**
46+
* Configure client services
47+
*
48+
* @param ContainerBuilder $container
49+
* @param array $config
50+
*/
51+
protected function configureClients(ContainerBuilder $container, array $config)
52+
{
4153
$first = isset($config['clients']['default']) ? 'default' : null;
4254
foreach ($config['clients'] as $name => $arguments) {
4355
if ($first === null) {
4456
$first = $name;
4557
}
4658

4759
$def = $container->register('httplug.client.'.$name, DummyClient::class);
48-
$def->setFactory([new Reference($arguments['factory']), 'createClient'])
49-
->addArgument($arguments['config']);
60+
61+
if (empty($arguments['plugins'])) {
62+
$def->setFactory([new Reference($arguments['factory']), 'createClient'])
63+
->addArgument($arguments['config']);
64+
} else {
65+
$def->setFactory('Http\HttplugBundle\ClientFactory\PluginClientFactory::createPluginClient')
66+
->addArgument(array_map(function($id) {
67+
return new Reference($id);
68+
}, $arguments['plugins']))
69+
->addArgument(new Reference($arguments['factory']))
70+
->addArgument($arguments['config']);
71+
}
72+
5073
}
5174

75+
// Alias the first client to httplug.client.default
5276
if ($first !== null) {
5377
$container->setAlias('httplug.client.default', 'httplug.client.'.$first);
5478
}

README.md

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,26 @@ For information how to write applications with the services provided by this bun
4343

4444
#### Custom services
4545

46-
This bundle provides 3 services:
4746

48-
* `httplug.client` a service that provides the `Http\Client\HttpClient`
49-
* `httplug.message_factory` a service that provides the `Http\Message\MessageFactory`
50-
* `httplug.uri_factory` a service that provides the `Http\Message\UriFactory`
51-
* `httplug.stream_factory` a service that provides the `Http\Message\StreamFactory`
47+
| Service id | Description |
48+
| ---------- | ----------- |
49+
| httplug.message_factory | Service* that provides the `Http\Message\MessageFactory`
50+
| httplug.uri_factory | Service* that provides the `Http\Message\UriFactory`
51+
| httplug.stream_factory | Service* that provides the `Http\Message\StreamFactory`
52+
| httplug.client.[name] | This is your Httpclient that you have configured. With the configuration below the name would be `acme_client`.
53+
| httplug.client | This is the first client configured or a client named `default`.
54+
| httplug.plugin.content_length <br> httplug.plugin.decoder<br> httplug.plugin.error<br> httplug.plugin.logger<br> httplug.plugin.redirect<br> httplug.plugin.retry | These are build in plugins that lives in the `php-http/plugins` package. These servcies are not public and may only be used when configure HttpClients or services.
5255

53-
These services are always an alias to another service. You can specify your own service or leave the default, which is the same name with `.default` appended. The default services in turn use the service discovery mechanism to provide the best available implementation. You can specify a class for each of the default services to use instead of discovery, as long as those classes can be instantiated without arguments.
56+
\* *These services are always an alias to another service. You can specify your own service or leave the default, which is the same name with `.default` appended. The default services in turn use the service discovery mechanism to provide the best available implementation. You can specify a class for each of the default services to use instead of discovery, as long as those classes can be instantiated without arguments.*
5457

5558
If you need a more custom setup, define the services in your application configuration and specify your service in the `main_alias` section. For example, to add authentication headers, you could define a service that decorates the service `httplug.client.default` with a plugin that injects the authentication headers into the request and configure `httplug.main_alias.client` to the name of your service.
5659

5760
```yaml
5861
httplug:
62+
clients:
63+
acme_client: # This is the name of the client
64+
factory: 'httplug.factory.guzzle6'
65+
5966
main_alias:
6067
client: httplug.client.default
6168
message_factory: httplug.message_factory.default
@@ -80,16 +87,16 @@ httplug:
8087
factory: 'httplug.factory.guzzle5'
8188
config:
8289
# These options are given to Guzzle without validation.
83-
base_url: 'http://google.se/'
8490
defaults:
91+
base_uri: 'http://google.se/'
8592
verify_ssl: false
8693
timeout: 4
8794
headers:
8895
Content-Type: 'application/json'
8996
acme:
9097
factory: 'httplug.factory.guzzle6'
9198
config:
92-
base_url: 'http://google.se/'
99+
base_uri: 'http://google.se/'
93100

94101
```
95102

@@ -99,6 +106,28 @@ $httpClient = $this->container->get('httplug.client.my_guzzle5');
99106
$httpClient = $this->container->get('httplug.client.acme');
100107
```
101108

109+
#### Plugins
110+
111+
You can configure the clients with plugins.
112+
113+
```yaml
114+
// services.yml
115+
acme_plugin:
116+
class: Acme\Plugin\MyCustonPlugin
117+
arguments: ["%api_key%"]
118+
```
119+
```yaml
120+
// config.yml
121+
httpug:
122+
clients:
123+
acme:
124+
factory: 'httplug.factory.guzzle6'
125+
plugins: ['acme_plugin' , 'httplug.plugin.logger']
126+
config:
127+
base_uri: 'http://google.se/'
128+
```
129+
130+
102131
### Use for Reusable Bundles
103132
104133
Rather than code against specific HTTP clients, you want to use the Httplug `Client` interface. To avoid building your own infrastructure to define services for the client, simply `require: php-http/httplug-bundle` in your bundles `composer.json`. You SHOULD provide configuration for each of your services that needs an HTTP client to specify the service to use, defaulting to `httplug.client`. This way, the default case needs no additional configuration for your users.

Resources/config/plugins.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<container xmlns="http://symfony.com/schema/dic/services"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
5+
6+
<services>
7+
<service id="httplug.plugin.content_length" class="Http\Client\Plugin\ContentLengthPlugin" public="false" />
8+
<service id="httplug.plugin.decoder" class="Http\Client\Plugin\DecoderPlugin" public="false">
9+
</service>
10+
<service id="httplug.plugin.error" class="Http\Client\Plugin\ErrorPlugin" public="false" />
11+
<service id="httplug.plugin.logger" class="Http\Client\Plugin\LoggerPlugin" public="false">
12+
<argument type="service" id="logger"/>
13+
</service>
14+
<service id="httplug.plugin.redirect" class="Http\Client\Plugin\RedirectPlugin" public="false" />
15+
<service id="httplug.plugin.retry" class="Http\Client\Plugin\RetryPlugin" public="false" />
16+
</services>
17+
</container>

0 commit comments

Comments
 (0)