10000 [FrameworkBundle] Add integration of http-client component by Ioni14 · Pull Request #30419 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[FrameworkBundle] Add integration of http-client component #30419

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 17, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
work with attributes for xml config
  • Loading branch information
nicoweb authored and nicolas-grekas committed Mar 17, 2019
commit f2d2cf3021f9a86b8603d3c6696fd428feea606f
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\Lock\Lock;
use Symfony\Component\Lock\Store\SemaphoreStore;
Expand Down 10000 Expand Up @@ -1179,7 +1180,7 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode)
->children()
->arrayNode('http_client')
->info('HTTP Client configuration')
->canBeEnabled()
->{!class_exists(FullStack::class) && class_exists(HttpClient::class) ? 'canBeDisabled' : 'canBeEnabled'}()
->fixXmlConfig('client')
->children();

Expand Down Expand Up @@ -1213,12 +1214,27 @@ private function addHttpClientOptionsSection(NodeBuilder $rootNode)
->arrayNode('default_options')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the default options for each request that's made. What about default_request_options (it's even documented as Default requests' options in HttpClient phpdoc). And also, should we make these options not automatically be used as the "default options" for all the other HTTP clients?

The problem is that there are 2 concepts conflicting right now. Does "default" mean:
A) default options for the request that can be overridden on each request
OR
B) default options that will be applied to all other HTTP clients

Right now, it's both - that confused me. It's really (A), so maybe we should make it only (A) and clarify the name.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right now, it is default options applied to all other HTTP clients for their default request options...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exactly - the "default" means to things - it's (A) and (B).

Copy link
Member
@nicolas-grekas nicolas-grekas Mar 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, it's A and B. If one wants to configure the default request options for the default client only, one should set them under framework.http_client.clients.http_client.default_options (since http_client is the name of the service that is aliased for HttpClientInterface).
I'm not sure I understand how your suggestion would apply. To me, all is fine :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was suggesting that we remove (B), but it's subjective. The question is: is it valuable for these options to cascade onto other clients? Or is it annoying/surprising, and then I am unsetting options on my individual clients, because I don't want them to cascade from my default client?

I'm not convinced that re-using options across clients will be all that common - things like auth, base_uri, headers all seem very client-specific. I could argue that it might be surprising if my auth on my default client starts getting sent to another server via another client (because I didn't realize the options would cascade down to my client).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.g. cabundle/capath: you want to configure them once for all

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, ok, really fine by me then.

->fixXmlConfig('header')
->children()
->scalarNode('auth')
->scalarNode('auth_basic')
->info('An HTTP Basic authentication "username:password".')
->end()
->scalarNode('auth_bearer')
->info('A token enabling HTTP Bearer authorization.')
->end()
->arrayNode('query')
->info('Associative array of query string values merged with URL parameters.')
->useAttributeAsKey('key')
->beforeNormalization()
->always(function ($config) {
if (!\is_array($config)) {
return [];
}
if (!isset($config['key'])) {
return $config;
}

return [$config['key'] => $config['value']];
})
->end()
->normalizeKeys(false)
->scalarPrototype()->end()
->end()
Expand All @@ -1237,12 +1253,21 @@ private function addHttpClientOptionsSection(NodeBuilder $rootNode)
->scalarNode('base_uri')
->info('The URI to resolve relative URLs, following rules in RFC 3986, section 2.')
->end()
->booleanNode('buffer')
->info('Indicates if the response should be buffered or not.')
->end()
->arrayNode('resolve')
->info('Associative array: domain => IP.')
->useAttributeAsKey('host')
->beforeNormalization()
->always(function ($config) {
if (!\is_array($config)) {
return [];
}
if (!isset($config['host'])) {
return $config;
}

return [$config['host'] => $config['value']];
})
->end()
->normalizeKeys(false)
->scalarPrototype()->end()
->end()
Expand Down Expand Up @@ -1284,9 +1309,12 @@ private function addHttpClientOptionsSection(NodeBuilder $rootNode)
->end()
->arrayNode('peer_fingerprint')
->info('Associative array: hashing algorithm => hash(es).')
->useAttributeAsKey('algo')
->normalizeKeys(false)
->variablePrototype()->end()
->children()
->variableNode('sha1')->end()
->variableNode('pin-sha256')->end()
->variableNode('md5')->end()
->end()
->end()
->end()
->end()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1771,9 +1771,16 @@ private function registerHttpClientConfiguration(array $config, ContainerBuilder
public function merge(array $options, array $defaultOptions)
{
try {
[, $options] = $this->prepareRequest(null, null, $options, $defaultOptions);
[, $mergedOptions] = $this->prepareRequest(null, null, $options, $defaultOptions);

return $options;
foreach ($mergedOptions as $k => $v) {
if (!isset($options[$k]) && !isset($defaultOptions[$k])) {
// Remove options added by prepareRequest()
unset($mergedOptions[$k]);
}
}

return $mergedOptions;
} catch (TransportExceptionInterface $e) {
throw new InvalidArgumentException($e->getMessage(), 0, $e);
}
Expand All @@ -1783,19 +1790,27 @@ public function merge(array $options, array $defaultOptions)
$defaultOptions = $merger->merge($config['default_options'] ?? [], []);
$container->getDefinition('http_client')->setArguments([$defaultOptions, $config['max_host_connections'] ?? 6]);

if (!$hasPsr18 = interface_exists(ClientInterface::class)) {
$container->removeDefinition('psr18.http_client');
$container->removeAlias(ClientInterface::class);
}

foreach ($config['clients'] as $name => $clientConfig) {
$options = $merger->merge($clientConfig['default_options'] ?? [], $defaultOptions);

$container->register($name, HttpClientInterface::class)
->setFactory([HttpClient::class, 'create'])
->setArguments([$options, $clientConfig['max_host_connections'] ?? $config['max_host_connections'] ?? 6]);

$container->register('psr18.'.$name, Psr18Client::class)
->setAutowired(true)
->setArguments([new Reference($name)]);

$container->registerAliasForArgument($name, HttpClientInterface::class);
$container->registerAliasForArgument('psr18.'.$name, ClientInterface::class, $name);

if ($hasPsr18) {
$container->register('psr18.'.$name, Psr18Client::class)
->setAutowired(true)
->setArguments([new Reference($name)]);

$container->registerAliasForArgument('psr18.'.$name, ClientInterface::class, $name);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<xsd:element name="php-errors" type="php-errors" minOccurs="0" maxOccurs="1" />
<xsd:element name="lock" type="lock" minOccurs="0" maxOccurs="1" />
<xsd:element name="messenger" type="messenger" minOccurs="0" maxOccurs="1" />
<xsd:element name="http_client" type="http_client" minOccurs="0" maxOccurs="1" />
<xsd:element name="http-client" type="http_client" minOccurs="0" maxOccurs="1" />
</xsd:choice>

<xsd:attribute name="http-method-override" type="xsd:boolean" />
Expand Down Expand Up @@ -448,61 +448,63 @@

<xsd:complexType name="http_client">
<xsd:sequence>
<xsd:element name="max_host_connections" type="xsd:integer" minOccurs="0" />
<xsd:element name="default_options" type="http_client_options" minOccurs="0" />
<xsd:element name="default-options" type="http_client_options" minOccurs="0" />
<xsd:element name="client" type="http_client_client" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="enabled" type="xsd:boolean" />
<xsd:attribute name="max-host-connections" type="xsd:integer" />
</xsd:complexType>

<xsd:complexType name="http_client_options">
<xsd:sequence>
<xsd:element name="auth" type="xsd:string" minOccurs="0" />
<xsd:element name="query" type="http_query" minOccurs="0" />
<xsd:element name="headers" type="http_headers" minOccurs="0" />
<xsd:element name="max_redirects" type="xsd:integer" minOccurs="0" />
<xsd:element name="http_version" type="xsd:string" minOccurs="0" />
<xsd:element name="base_uri" type="xsd:string" minOccurs="0" />
<xsd:element name="buffer" type="xsd:boolean" minOccurs="0" />
<xsd:element name="resolve" type="metadata" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="proxy" type="xsd:string" minOccurs="0" />
<xsd:element name="no_proxy" type="xsd:string" minOccurs="0" />
<xsd:element name="timeout" type="xsd:float" minOccurs="0" />
<xsd:element name="bindto" type="xsd:string" minOccurs="0" />
<xsd:element name="verify_peer" type="xsd:boolean" minOccurs="0" />
<xsd:element name="verify_host" type="xsd:boolean" minOccurs="0" />
<xsd:element name="cafile" type="xsd:string" minOccurs="0" />
<xsd:element name="capath" type="xsd:string" minOccurs="0" />
<xsd:element name="local_cert" type="xsd:string" minOccurs="0" />
<xsd:element name="local_pk" type="xsd:string" minOccurs="0" />
<xsd:element name="passphrase" type="xsd:string" minOccurs="0" />
<xsd:element name="ciphers" type="xsd:string" minOccurs="0" />
<xsd:element name="peer_fingerprint" type="fingerprint" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:complexType name="http_client_options" mixed="true">
<xsd:choice maxOccurs="unbounded">
<xsd:element name="query" type="http_query" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="resolve" type="http_resolve" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="header" type="http_header" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="peer-fingerprint" type="fingerprint" minOccurs="0" maxOccurs="unbounded" />
</xsd:choice>
<xsd:attribute name="proxy" type="xsd:string" />
<xsd:attribute name="timeout" type="xsd:float" />
<xsd:attribute name="bindto" type="xsd:string" />
<xsd:attribute name="verify-peer" type="xsd:boolean" />
<xsd:attribute name="auth-basic" type="xsd:string" />
<xsd:attribute name="auth-bearer" type="xsd:string" />
<xsd:attribute name="max-redirects" type="xsd:integer" />
<xsd:attribute name="http-version" type="xsd:string" />
<xsd:attribute name="base-uri" type="xsd:string" />
<xsd:attribute name="no-proxy" type="xsd:string" />
<xsd:attribute name="verify-host" type="xsd:boolean" />
<xsd:attribute name="cafile" type="xsd:string" />
<xsd:attribute name="capath" type="xsd:string" />
<xsd:attribute name="local-cert" type="xsd:string" />
<xsd:attribute name="local-pk" type="xsd:string" />
<xsd:attribute name="passphrase" type="xsd:string" />
<xsd:attribute name="ciphers" type="xsd:string" />
</xsd:complexType>

<xsd:complexType name="http_client_client">
<xsd:sequence>
<xsd:element name="default_options" type="http_client_options" minOccurs="0" />
<xsd:element name="default-options" type="http_client_options" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>

<xsd:complexType name="fingerprint">
<xsd:sequence>
<xsd:any minOccurs="0" processContents="lax" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="pin-sha256" type="xsd:string" minOccurs="0" />
<xsd:element name="sha1" type="xsd:string" minOccurs="0" />
<xsd:element name="md5" type="xsd:string" minOccurs="0" />
</xsd:choice>
</xsd:complexType>

<xsd:complexType name="http_query">
<xsd:sequence>
<xsd:any minOccurs="0" processContents="lax" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:complexType name="http_query" mixed="true">
<xsd:attribute name="key" type="xsd:string" />
</xsd:complexType>

<xsd:complexType name="http_headers">
<xsd:sequence>
<xsd:any minOccurs="0" processContents="lax" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:complexType name="http_resolve" mixed="true">
<xsd:attribute name="host" type="xsd:string" />
</xsd:complexType>

<xsd:complexType name="http_header" mixed="true">
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:schema>
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Symfony\Bundle\FullStack;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\Lock\Store\SemaphoreStore;
use Symfony\Component\Messenger\MessageBusInterface;

Expand Down Expand Up @@ -332,8 +333,7 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor
],
'disallow_search_engine_index' => true,
'http_client' => [
'enabled' => false,
'max_host_connections' => 6,
'enabled' => !class_exists(FullStack::class) && class_exists(HttpClient::class),
'clients' => [],
],
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
$container->loadFromExtension('framework', [
'http_client' => [
'default_options' => [
'auth' => 'foo:bar',
'auth_basic' => 'foo:bar',
'query' => ['foo' => 'bar', 'bar' => 'baz'],
'headers' => ['X-powered' => 'PHP'],
'max_redirects' => 2,
'http_version' => '2.0',
'base_uri' => 'http://example.com',
'buffer' => true,
'resolve' => ['localhost' => '127.0.0.1'],
'proxy' => 'proxy.org',
'timeout' => 3.5,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">

<framework:config>
<framework:http_client>
<framework:max_host_connections>4</framework:max_host_connections>
<framework:default_options />
<framework:http-client max-host-connections="4">
<framework:default-options />
<framework:client name="foo">
<framework:default_options />
<framework:default-options />
</framework:client>
</framework:http_client>
</framework:http-client>
</framework:config>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,34 @@
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">

<framework:config>
<framework:http_client>
<framework:default_options>
<framework:auth>foo:bar</framework:auth>
<framework:query>
<framework:foo>bar</framework:foo>
<framework:bar>baz</framework:bar>
</framework:query>
<framework:headers>
<framework:X-powered>PHP</framework:X-powered>
</framework:headers>
<framework:max_redirects>2</framework:max_redirects>
<framework:http_version>2.0</framework:http_version>
<framework:base_uri>http://example.com</framework:base_uri>
<framework:buffer>true</framework:buffer>
<framework:resolve>
<framework:localhost>127.0.0.1</framework:localhost>
</framework:resolve>
<framework:proxy>proxy.org</framework:proxy>
<framework:timeout>3.5</framework:timeout>
<framework:bindto>127.0.0.1</framework:bindto>
<framework:verify_peer>true</framework:verify_peer>
<framework:verify_host>true</framework:verify_host>
<framework:cafile>/etc/ssl/cafile</framework:cafile>
<framework:capath>/etc/ssl</framework:capath>
<framework:local_cert>/etc/ssl/cert.pem</framework:local_cert>
<framework:local_pk>/etc/ssl/private_key.pem</framework:local_pk>
<framework:passphrase>password123456</framework:passphrase>
<framework:ciphers>RC4-SHA:TLS13-AES-128-GCM-SHA256</framework:ciphers>
<framework:peer_fingerprint>
<framework:http-client>
<framework:default-options
proxy="proxy.org"
bindto="127.0.0.1"
timeout="3.5"
verify-peer="true"
auth-basic="foo:bar"
max-redirects="2"
http-version="2.0"
base-uri="http://example.com"
verify-host="true"
cafile="/etc/ssl/cafile"
capath="/etc/ssl"
local-cert="/etc/ssl/cert.pem"
local-pk="/etc/ssl/private_key.pem"
passphrase="password123456"
ciphers="RC4-SHA:TLS13-AES-128-GCM-SHA256"
>
<framework:query key="foo">bar</framework:query>
<framework:query key="bar">baz</framework:query>
<framework:header name="X-powered">PHP</framework:header>
<framework:resolve host="localhost">127.0.0.1</framework:resolve>
<framework:peer-fingerprint>
<framework:pin-sha256>14s5erg62v1v8471g2revg48r7==</framework:pin-sha256>
<framework:pin-sha256>jsda84hjtyd4821bgfesd215bsfg5412=</framework:pin-sha256>
<framework:md5>sdhtb481248721thbr=</framework:md5>
</framework:peer_fingerprint>
</framework:default_options>
</framework:http_client>
</framework:peer-fingerprint>
</framework:default-options>
</framework:http-client>
</framework:config>
</container>
< 98D /deferred-diff-lines>
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,15 @@
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">

<framework:config>
<framework:http_client>
<framework:default_options>
<framework:headers>
<framework:foo>bar</framework:foo>
</framework:headers>
</framework:default_options>
<framework:http-client>
<framework:default-options>
<framework:header name="foo">bar</framework:header>
</framework:default-options>
<framework:client name="foo">
<framework:default_options>
<framework:headers>
<framework:bar>baz</framework:bar>
</framework:headers>
</framework:default_options>
<framework:default-options>
<framework:header name="bar">baz</framework:header>
</framework:default-options>
</framework:client>
</framework:http_client>
</framework:http-client>
</framework:config>
</container>
Loading
0