Skip to content

Commit 0452bf6

Browse files
committed
Move handleContentType + regex validation + unit testing
1 parent 6faabf7 commit 0452bf6

File tree

7 files changed

+79
-101
lines changed

7 files changed

+79
-101
lines changed

src/Symfony/Component/HttpClient/HttpClientTrait.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ private static function prepareRequest(?string $method, ?string $url, array $opt
4242

4343
$options = self::mergeDefaultOptions($options, $defaultOptions, $allowExtraOptions);
4444

45+
if (isset($options['buffer']) && \is_string($options['buffer'])) {
46+
try {
47+
preg_match($options['buffer'], null);
48+
} catch (\Exception $exception) {
49+
throw new InvalidArgumentException('Please provide a valid regex');
50+
}
51+
}
52+
4553
if (isset($options['json'])) {
4654
if (isset($options['body']) && '' !== $options['body']) {
4755
throw new InvalidArgumentException('Define either the "json" or the "body" option, setting both is not supported.');

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ public function __construct(CurlClientState $multi, $ch, array $options = null,
6363
}
6464

6565
if (null === $content = &$this->content) {
66-
$content = ($options['buffer'] ?? true) ? fopen('php://temp', 'w+') : null;
66+
$content = isset($options['buffer']) && true === $options['buffer'] ? fopen('php://temp', 'w+') : null;
6767
} else {
6868
// Move the pushed response to the activity list
6969
if (ftell($content)) {
7070
rewind($content);
7171
$multi->handlesActivity[$id][] = stream_get_contents($content);
7272
}
73-
$content = ($options['buffer'] ?? true) ? $content : null;
73+
$content = isset($options['buffer']) && true === $options['buffer'] ? $content : null;
7474
}
7575

7676
curl_setopt($ch, CURLOPT_HEADERFUNCTION, static function ($ch, string $data) use (&$info, &$headers, $options, $multi, $id, &$location, $resolveRedirect, $logger, &$content): int {
@@ -277,7 +277,7 @@ private static function select(CurlClientState $multi, float $timeout): int
277277
/**
278278
* Parses header lines as curl yields them to us.
279279
*/
280-
private static function parseHeaderLine($ch, string $data, array &$info, array &$headers, ?array &$options, CurlClientState $multi, int $id, ?string &$location, ?callable $resolveRedirect, ?LoggerInterface $logger, &$content = null): int
280+
private static function parseHeaderLine($ch, string $data, array &$info, array &$headers, ?array $options, CurlClientState $multi, int $id, ?string &$location, ?callable $resolveRedirect, ?LoggerInterface $logger, &$content = null): int
281281
{
282282
if (!\in_array($waitFor = @curl_getinfo($ch, CURLINFO_PRIVATE), ['headers', 'destruct'], true)) {
283283
return \strlen($data); // Ignore HTTP trailers
@@ -287,9 +287,6 @@ private static function parseHeaderLine($ch, string $data, array &$info, array &
287287
// Regular header line: add it to the list
288288

289289
self::addResponseHeaders([substr($data, 0, -2)], $info, $headers);
290-
if (isset($headers['content-type'], $options['buffer']) && \is_string($options['buffer'])) {
291-
self::handleContentType($content, $headers['content-type'][0], $options['buffer']);
292-
}
293290

294291
if (0 !== strpos($data, 'HTTP/')) {
295292
if (0 === stripos($data, 'Location:')) {
@@ -349,6 +346,10 @@ private static function parseHeaderLine($ch, string $data, array &$info, array &
349346
return 0;
350347
}
351348

349+
if (isset($headers['content-type'], $options['buffer']) && \is_string($options['buffer'])) {
350+
self::handleContentType($content, $headers['content-type'][0], $options['buffer']);
351+
}
352+
352353
curl_setopt($ch, CURLOPT_PRIVATE, 'content');
353354
} elseif (null !== $info['redirect_url'] && $logger) {
354355
$logger->info(sprintf('Redirecting: "%s %s"', $info['http_code'], $info['redirect_url']));

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function __construct(NativeClientState $multi, $context, string $url, $op
5151
$this->info = &$info;
5252
$this->resolveRedirect = $resolveRedirect;
5353
$this->onProgress = $onProgress;
54-
$this->content = $options['buffer'] ? fopen('php://temp', 'w+') : null;
54+
$this->content = isset($options['buffer']) && true === $options['buffer'] ? fopen('php://temp', 'w+') : null;
5555
$this->bufferRegex = isset($options['buffer']) && \is_string($options['buffer']) ? $options['buffer'] : null;
5656

5757
// Temporary resources to dechunk/inflate the response stream
@@ -132,9 +132,6 @@ private function open(): void
132132
// Send request and follow redirects when needed
133133
$this->handle = $h = fopen($url, 'r', false, $this->context);
134134
self::addResponseHeaders($http_response_header, $this->info, $this->headers, $this->info['debug']);
135-
if (null !== $this->bufferRegex && isset($this->headers['content-type'])) {
136-
self::handleContentType($this->content, $this->headers['content-type'][0], $this->bufferRegex);
137-
}
138135

139136
$url = ($this->resolveRedirect)($this->multi, $this->headers['location'][0] ?? null, $this->context);
140137

@@ -158,6 +155,10 @@ private function open(): void
158155
stream_set_blocking($h, false);
159156
$this->context = $this->resolveRedirect = null;
160157

158+
if (null !== $this->bufferRegex && isset($this->headers['content-type'])) {
159+
self::handleContentType($this->content, $this->headers['content-type'][0], $this->bufferRegex);
160+
}
161+
161162
if (isset($context['ssl']['peer_certificate_chain'])) {
162163
$this->info['peer_certificate_chain'] = $context['ssl']['peer_certificate_chain'];
163164
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ private static function addResponseHeaders(array $responseHeaders, array &$info,
246246

247247
private static function handleContentType(&$content, string $contentType, string $bufferRegex): void
248248
{
249-
$contentType = substr($contentType, 0, strpos($contentType, ';'));
249+
$contentType = substr($contentType, 0, (false !== strpos($contentType, ';') ? strpos($contentType, ';') : \strlen($contentType)));
250250
if (null === $content && preg_match($bufferRegex, $contentType)) {
251251
$content = fopen('php://temp', 'w+');
252252
}

src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -71,49 +71,4 @@ public function log($level, $message, array $context = [])
7171
];
7272
$this->assertSame($expected, $logger->logs);
7373
}
74-
75-
public function testJsonRegexBuffer(): void
76-
{
77-
$client = new CurlHttpClient(['buffer' => '/([a-z]+\/json$)/']);
78-
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');
79-
80-
$firstContent = $response->getContent();
81-
$secondContent = $response->getContent();
82-
83-
$this->assertSame($firstContent, $secondContent);
84-
}
85-
86-
public function testPdfRegexBuffer(): void
87-
{
88-
$client = new CurlHttpClient(['buffer' => '/application\/pdf$/']);
89-
$response = $client->request('GET', 'http://s2.q4cdn.com/235752014/files/doc_downloads/test.pdf');
90-
91-
$firstContent = $response->getContent();
92-
$secondContent = $response->getContent();
93-
94-
$this->assertSame($firstContent, $secondContent);
95-
}
96-
97-
/**
98-
* @expectedException \Symfony\Component\HttpClient\Exception\TransportException
99-
*/
100-
public function testFalseBuffer(): void
101-
{
102-
$client = new CurlHttpClient(['buffer' => false]);
103-
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');
104-
105-
$firstPosts = $response->getContent();
106-
$secondPosts = $response->getContent();
107-
}
108-
109-
public function testTrueBuffer(): void
110-
{
111-
$client = new CurlHttpClient(['buffer' => true]);
112-
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');
113-
114-
$firstContent = $response->getContent();
115-
$secondContent = $response->getContent();
116-
117-
$this->assertSame($firstContent, $secondContent);
118-
}
11974
}

src/Symfony/Component/HttpClient/Tests/NativeHttpClientTest.php

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -20,49 +20,4 @@ protected function getHttpClient(string $testCase): HttpClientInterface
2020
{
2121
return new NativeHttpClient();
2222
}
23-
24-
public function testJsonRegexBuffer(): void
25-
{
26-
$client = new NativeHttpClient(['buffer' => '/([a-z]+\/json$)/']);
27-
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');
28-
29-
$firstContent = $response->getContent();
30-
$secondContent = $response->getContent();
31-
32-
$this->assertSame($firstContent, $secondContent);
33-
}
34-
35-
public function testPdfRegexBuffer(): void
36-
{
37-
$client = new NativeHttpClient(['buffer' => '/application\/pdf$/']);
38-
$response = $client->request('GET', 'http://s2.q4cdn.com/235752014/files/doc_downloads/test.pdf');
39-
40-
$firstContent = $response->getContent();
41-
$secondContent = $response->getContent();
42-
43-
$this->assertSame($firstContent, $secondContent);
44-
}
45-
46-
/**
47-
* @expectedException \Symfony\Component\HttpClient\Exception\TransportException
48-
*/
49-
public function testFalseBuffer(): void
50-
{
51-
$client = new NativeHttpClient(['buffer' => false]);
52-
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');
53-
54-
$firstPosts = $response->getContent();
55-
$secondPosts = $response->getContent();
56-
}
57-
58-
public function testTrueBuffer(): void
59-
{
60-
$client = new NativeHttpClient(['buffer' => true]);
61-
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');
62-
63-
$firstContent = $response->getContent();
64-
$secondContent = $response->getContent();
65-
66-
$this->assertSame($firstContent, $secondContent);
67-
}
6823
}

src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,4 +763,62 @@ public function testGzipBroken()
763763
$this->expectException(TransportExceptionInterface::class);
764764
$response->getContent();
765765
}
766+
767+
public function testJsonRegexBuffer(): void
768+
{
769+
$client = $this->getHttpClient(__FUNCTION__);
770+
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users', ['buffer' => '/([a-z]+\/json)/']);
771+
772+
$firstContent = $response->getContent();
773+
$secondContent = $response->getContent();
774+
775+
$this->assertSame($firstContent, $secondContent);
776+
}
777+
778+
/**
779+
* @expectedException \Symfony\Component\HttpClient\Exception\TransportException
780+
*/
781+
public function testFalseBuffer(): void
782+
{
783+
$client = $this->getHttpClient(__FUNCTION__);
784+
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users', ['buffer' => false]);
785+
786+
$firstPosts = $response->getContent();
787+
$secondPosts = $response->getContent();
788+
}
789+
790+
/**
791+
* @expectedException \Symfony\Component\HttpClient\Exception\InvalidArgumentException
792+
*/
793+
public function testInvalidRegexBuffer(): void
794+
{
795+
$client = $this->getHttpClient(__FUNCTION__);
796+
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users', ['buffer' => '/([a-z]+\/json))/']);
797+
798+
$firstPosts = $response->getContent();
799+
$secondPosts = $response->getContent();
800+
}
801+
802+
/**
803+
* @expectedException \Symfony\Component\HttpClient\Exception\InvalidArgumentException
804+
*/
805+
public function testPdfRegexBuffer(): void
806+
{
807+
$client = $this->getHttpClient(__FUNCTION__);
808+
$response = $client->request('GET', 'http://localhost:8057', ['buffer' => '/([a-z]+\/json))/']);
809+
810+
$firstContent = $response->getContent();
811+
$secondContent = $response->getContent();
812+
}
813+
814+
public function testTrueBuffer(): void
815+
{
816+
$client = $this->getHttpClient(__FUNCTION__);
817+
$response = $client->request('GET', 'http://localhost:8057', ['buffer' => true]);
818+
819+
$firstContent = $response->getContent();
820+
$secondContent = $response->getContent();
821+
822+
$this->assertSame($firstContent, $secondContent);
823+
}
766824
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy