8000 Merge branch '4.3' into 4.4 · symfony/symfony@fb2d257 · GitHub
[go: up one dir, main page]

Skip to content

Commit fb2d257

Browse files
Merge branch '4.3' into 4.4
* 4.3: [HttpClient] Don't read from the network faster than the CPU can deal with [DI] DecoratorServicePass should keep container.service_locator on the decorated definition
2 parents 9d4c98e + f9b36c7 commit fb2d257

File tree

8 files changed

+129
-164
lines changed

8 files changed

+129
-164
lines changed

src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,18 @@ public function process(ContainerBuilder $container)
7878

7979
if (isset($decoratingDefinitions[$inner])) {
8080
$decoratingDefinition = $decoratingDefinitions[$inner];
81-
$definition->setTags(array_merge($decoratingDefinition->getTags(), $definition->getTags()));
82-
$decoratingDefinition->setTags([]);
81+
82+
$decoratingTags = $decoratingDefinition->getTags();
83+
$resetTags = [];
84+
85+
if (isset($decoratingTags['container.service_locator'])) {
86+
// container.service_locator has special logic and it must not be transferred out to decorators
87+
$resetTags = ['container.service_locator' => $decoratingTags['container.service_locator']];
88+
unset($decoratingTags['container.service_locator']);
89+
}
90+
91+
$definition->setTags(array_merge($decoratingTags, $definition->getTags()));
92+
$decoratingDefinition->setTags($resetTags);
8393
$decoratingDefinitions[$inner] = $definition;
8494
}
8595

src/Symfony/Component/DependencyInjection/Tests/Compiler/DecoratorServicePassTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,25 @@ public function testProcessMovesTagsFromDecoratedDefinitionToDecoratingDefinitio
223223
$this->assertEquals(['bar' => ['attr' => 'baz']], $container->getDefinition('deco2')->getTags());
224224
}
225225

226+
public function testProcessLeavesServiceLocatorTagOnOriginalDefinition()
227+
{
228+
$container = new ContainerBuilder();
229+
$container
230+
->register('foo')
231+
->setTags(['container.service_locator' => [0 => []], 'bar' => ['attr' => 'baz']])
232+
;
233+
$container
234+
->register('baz')
235+
->setTags(['foobar' => ['attr' => 'bar']])
236+
->setDecoratedService('foo')
237+
;
238+
239+
$this->process($container);
240+
241+
$this->assertEquals(['container.service_locator' => [0 => []]], $container->getDefinition('baz.inner')->getTags());
242+
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar']], $container->getDefinition('baz')->getTags());
243+
}
244+
226245
protected function process(ContainerBuilder $container)
227246
{
228247
$repeatedPass = new DecoratorServicePass();

src/Symfony/Component/HttpClient/CurlHttpClient.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public function request(string $method, string $url, array $options = []): Respo
116116
$url = implode('', $url);
117117

118118
if (!isset($options['normalized_headers']['user-agent'])) {
119-
$options['normalized_headers']['user-agent'][] = $options['headers'][] = 'User-Agent: Symfony HttpClient/Curl';
119+
$options['headers'][] = 'User-Agent: Symfony HttpClient/Curl';
120120
}
121121

122122
$curlopts = [
@@ -217,8 +217,8 @@ public function request(string $method, string $url, array $options = []): Respo
217217
$curlopts[CURLOPT_NOSIGNAL] = true;
218218
}
219219

220-
if (!isset($options['normalized_headers']['accept-encoding']) && CURL_VERSION_LIBZ & self::$curlVersion['features']) {
221-
$curlopts[CURLOPT_ENCODING] = 'gzip'; // Expose only one encoding, some servers mess up when more are provided
220+
if (\extension_loaded('zlib') && !isset($options['normalized_headers']['accept-encoding'])) {
221+
$options['headers'][] = 'Accept-Encoding: gzip'; // Expose only one encoding, some servers mess up when more are provided
222222
}
223223

224224
foreach ($options['headers'] as $header) {

src/Symfony/Component/HttpClient/NativeHttpClient.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public function request(string $method, string $url, array $options = []): Respo
7777
$options['headers'][] = 'Content-Type: application/x-www-form-urlencoded';
7878
}
7979

80-
if ($gzipEnabled = \extension_loaded('zlib') && !isset($options['normalized_headers']['accept-encoding'])) {
80+
if (\extension_loaded('zlib') && !isset($options['normalized_headers']['accept-encoding'])) {
8181
// gzip is the most widely available algo, no need to deal with deflate
8282
$options['headers'][] = 'Accept-Encoding: gzip';
8383
}
@@ -227,7 +227,7 @@ public function request(string $method, string $url, array $options = []): Respo
227227
$context = stream_context_create($context, ['notification' => $notification]);
228228
self::configureHeadersAndProxy($context, $host, $options['headers'], $proxy, $noProxy);
229229

230-
return new NativeResponse($this->multi, $context, implode('', $url), $options, $gzipEnabled, $info, $resolveRedirect, $onProgress, $this->logger);
230+
return new NativeResponse($this->multi, $context, implode('', $url), $options, $info, $resolveRedirect, $onProgress, $this->logger);
231231
}
232232

233233
/**

src/Symfony/Component/HttpClient/Response/CurlResponse.php

Lines changed: 15 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public function __construct(CurlClientState $multi, $ch, array $options = null,
5252

5353
$this->id = $id = (int) $ch;
5454
$this->logger = $logger;
55+
$this->shouldBuffer = $options['buffer'] ?? true;
5556
$this->timeout = $options['timeout'] ?? null;
5657
$this->info['http_method'] = $method;
5758
$this->info['user_data'] = $options['user_data'] ?? null;
@@ -65,50 +66,25 @@ public function __construct(CurlClientState $multi, $ch, array $options = null,
6566
curl_setopt($ch, CURLOPT_PRIVATE, \in_array($method, ['GET', 'HEAD', 'OPTIONS', 'TRACE'], true) && 1.0 < (float) ($options['http_version'] ?? 1.1) ? 'H2' : 'H0'); // H = headers + retry counter
6667
}
6768

68-
if (null === $content = &$this->content) {
69-
$content = null === $options || true === $options['buffer'] ? fopen('php://temp', 'w+') : (\is_resource($options['buffer']) ? $options['buffer'] : null);
70-
} else {
71-
// Move the pushed response to the activity list
72-
$buffer = $options['buffer'];
73-
74-
if ('H' !== curl_getinfo($ch, CURLINFO_PRIVATE)[0]) {
75-
if ($options['buffer'] instanceof \Closure) {
76-
try {
77-
[$content, $buffer] = [null, $content];
78-
[$content, $buffer] = [$buffer, $options['buffer']($headers)];
79-
} catch (\Throwable $e) {
80-
$multi->handlesActivity[$id][] = null;
81-
$multi->handlesActivity[$id][] = $e;
82-
[$content, $buffer] = [$buffer, false];
83-
}
84-
}
85-
86-
if (ftell($content)) {
87-
rewind($content);
88-
$multi->handlesActivity[$id][] = stream_get_contents($content);
89-
}
90-
}
91-
92-
if (\is_resource($buffer)) {
93-
$content = $buffer;
94-
} elseif (true !== $buffer) {
95-
$content = null;
96-
}
97-
}
98-
99-
curl_setopt($ch, CURLOPT_HEADERFUNCTION, static function ($ch, string $data) use (&$info, &$headers, $options, $multi, $id, &$location, $resolveRedirect, $logger, &$content): int {
100-
return self::parseHeaderLine($ch, $data, $info, $headers, $options, $multi, $id, $location, $resolveRedirect, $logger, $content);
69+
curl_setopt($ch, CURLOPT_HEADERFUNCTION, static function ($ch, string $data) use (&$info, &$headers, $options, $multi, $id, &$location, $resolveRedirect, $logger): int {
70+
return self::parseHeaderLine($ch, $data, $info, $headers, $options, $multi, $id, $location, $resolveRedirect, $logger);
10171
});
10272

10373
if (null === $options) {
10474
// Pushed response: buffer until requested
105-
curl_setopt($ch, CURLOPT_WRITEFUNCTION, static function ($ch, string $data) use (&$content): int {
106-
return fwrite($content, $data);
75+
curl_setopt($ch, CURLOPT_WRITEFUNCTION, static function ($ch, string $data) use ($multi, $id): int {
76+
$multi->handlesActivity[$id][] = $data;
77+
curl_pause($ch, CURLPAUSE_RECV);
78+
79+
return \strlen($data);
10780
});
10881

10982
return;
11083
}
11184

85+
$this->inflate = !isset($options['normalized_headers']['accept-encoding']);
86+
curl_pause($ch, CURLPAUSE_CONT);
87+
11288
if ($onProgress = $options['on_progress']) {
11389
$url = isset($info['url']) ? ['url' => $info['url']] : [];
11490
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
@@ -128,33 +104,16 @@ public function __construct(CurlClientState $multi, $ch, array $options = null,
128104
});
129105
}
130106

131-
curl_setopt($ch, CURLOPT_WRITEFUNCTION, static function ($ch, string $data) use (&$content, $multi, $id): int {
107+
curl_setopt($ch, CURLOPT_WRITEFUNCTION, static function ($ch, string $data) use ($multi, $id): int {
132108
$multi->handlesActivity[$id][] = $data;
133109

134-
return null !== $content ? fwrite($content, $data) : \strlen($data);
110+
return \strlen($data);
135111
});
136112

137113
$this->initializer = static function (self $response) {
138-
if (null !== $response->info['error']) {
139-
throw new TransportException($response->info['error']);
140-
}
141-
142114
$waitFor = curl_getinfo($ch = $response->handle, CURLINFO_PRIVATE);
143115

144-
if ('H' === $waitFor[0] || 'D' === $waitFor[0]) {
145-
try {
146-
foreach (self::stream([$response]) as $chunk) {
147-
if ($chunk->isFirst()) {
148-
break;
149-
}
150-
}
151-
} catch (\Throwable $e) {
152-
// Persist timeouts thrown during initialization
153-
$response->info['error'] = $e->getMessage();
154-
$response->close();
155-
throw $e;
156-
}
157-
}
116+
return 'H' === $waitFor[0] || 'D' === $waitFor[0];
158117
};
159118

160119
// Schedule the request in a non-blocking way
@@ -241,6 +200,7 @@ public function __destruct()
241200
*/
242201
private function close(): void
243202
{
203+
$this->inflate = null;
244204
unset($this->multi->openHandles[$this->id], $this->multi->handlesActivity[$this->id]);
245205
curl_setopt($this->handle, CURLOPT_PRIVATE, '_0');
246206

@@ -419,22 +379,6 @@ private static function parseHeaderLine($ch, string $data, array &$info, array &
419379
}
420380

421381
curl_setopt($ch, CURLOPT_PRIVATE, $waitFor);
422-
423-
try {
424-
if (!$content && $options['buffer'] instanceof \Closure && $content = $options['buffer']($headers) ?: null) {
425-
$content = \is_resource($content) ? $content : fopen('php://temp', 'w+');
426-
}
427-
428-
if (null !== $info['error']) {
429-
throw new TransportException($info['error']);
430-
}
431-
} catch (\Throwable $e) {
432-
$multi->handlesActivity[$id] = $multi->handlesActivity[$id] ?? [new FirstChunk()];
433-
$multi->handlesActivity[$id][] = null;
434-
$multi->handlesActivity[$id][] = $e;
435-
436-
return 0;
437-
}
438382
} elseif (null !== $info['redirect_url'] && $logger) {
439383
$logger->info(sprintf('Redirecting: "%s %s"', $info['http_code'], $info['redirect_url']));
440384
}

src/Symfony/Component/HttpClient/Response/MockResponse.php

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public function cancel(): void
9494
*/
9595
protected function close(): void
9696
{
97+
$this->inflate = null;
9798
$this->body = [];
9899
}
99100

@@ -105,22 +106,9 @@ public static function fromRequest(string $method, string $url, array $options,
105106
$response = new self([]);
106107
$response->requestOptions = $options;
107108
$response->id = ++self::$idSequence;
108-
109-
if (!($options['buffer'] ?? null) instanceof \Closure) {
110-
$response->content = true === ($options['buffer'] ?? true) ? fopen('php://temp', 'w+') : (\is_resource($options['buffer']) ? $options['buffer'] : null);
111-
}
109+
$response->shouldBuffer = $options['buffer'] ?? true;
112110
$response->initializer = static function (self $response) {
113-
if (null !== $response->info['error']) {
114-
throw new TransportException($response->info['error']);
115-
}
116-
117-
if (\is_array($response->body[0] ?? null)) {
118-
foreach (self::stream([$response]) as $chunk) {
119-
if ($chunk->isFirst()) {
120-
break;
121-
}
122-
}
123-
}
111+
return \is_array($response->body[0] ?? null);
124112
};
125113

126114
$response->info['redirect_count'] = 0;
@@ -198,11 +186,6 @@ protected static function perform(ClientState $multi, array &$responses): void
198186
} else {
199187
// Data or timeout chunk
200188
$multi->handlesActivity[$id][] = $chunk;
201-
202-
if (\is_string($chunk) && null !== $response->content) {
203-
// Buffer response body
204-
fwrite($response->content, $chunk);
205-
}
206189
}
207190
}
208191
}

0 commit comments

Comments
 (0)
0