Skip to content

Commit

Permalink
Use regex as buffer + tests + isset check
Browse files Browse the repository at this point in the history
  • Loading branch information
Ruben Jacobs committed Jul 18, 2019
1 parent 950166d commit f4ddd10
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 20 deletions.
4 changes: 2 additions & 2 deletions src/Symfony/Component/HttpClient/Response/CurlResponse.php
Expand Up @@ -287,8 +287,8 @@ private static function parseHeaderLine($ch, string $data, array &$info, array &
// Regular header line: add it to the list

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

if (0 !== strpos($data, 'HTTP/')) {
Expand Down
6 changes: 4 additions & 2 deletions src/Symfony/Component/HttpClient/Response/NativeResponse.php
Expand Up @@ -35,6 +35,7 @@ final class NativeResponse implements ResponseInterface
private $inflate;
private $multi;
private $debugBuffer;
private $bufferRegex;

/**
* @internal
Expand All @@ -51,6 +52,7 @@ public function __construct(NativeClientState $multi, $context, string $url, $op
$this->resolveRedirect = $resolveRedirect;
$this->onProgress = $onProgress;
$this->content = $options['buffer'] ? fopen('php://temp', 'w+') : null;
$this->bufferRegex = isset($options['buffer']) && is_string($options['buffer']) ? $options['buffer'] : null;

// Temporary resources to dechunk/inflate the response stream
$this->buffer = fopen('php://temp', 'w+');
Expand Down Expand Up @@ -130,8 +132,8 @@ private function open(): void
// Send request and follow redirects when needed
$this->handle = $h = fopen($url, 'r', false, $this->context);
self::addResponseHeaders($http_response_header, $this->info, $this->headers, $this->info['debug']);
if (\array_key_exists('content-type', $this->headers)) {
self::handleContentType($this->content, $this->headers['content-type'][0]);
if (null !== $this->bufferRegex && isset($this->headers['content-type'])) {
self::handleContentType($this->content, $this->headers['content-type'][0], $this->bufferRegex);
}

$url = ($this->resolveRedirect)($this->multi, $this->headers['location'][0] ?? null, $this->context);
Expand Down
5 changes: 2 additions & 3 deletions src/Symfony/Component/HttpClient/Response/ResponseTrait.php
Expand Up @@ -244,11 +244,10 @@ private static function addResponseHeaders(array $responseHeaders, array &$info,
}
}

private static function handleContentType(&$content, string $contentType)
private static function handleContentType(&$content, string $contentType, string $bufferRegex): void
{
$contentType = substr($contentType, 0, strpos($contentType, ';'));
if (1 === preg_match('/(text\/[a-z]+|[a-z]+\/(json|xml)$)/', $contentType) && null === $content) {
$options['buffer'] = true;
if (null === $content && preg_match($bufferRegex, $contentType)) {
$content = fopen('php://temp', 'w+');
}
}
Expand Down
42 changes: 29 additions & 13 deletions src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php
Expand Up @@ -13,6 +13,8 @@

use Psr\Log\AbstractLogger;
use Symfony\Component\HttpClient\CurlHttpClient;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
Expand Down Expand Up @@ -72,34 +74,48 @@ public function log($level, $message, array $context = [])
$this->assertSame($expected, $logger->logs);
}

public function testBufferForJson(): void
public function testJsonRegexBuffer(): void
{
$client = new CurlHttpClient(['buffer' => false]);
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/posts');
$client = new CurlHttpClient(['buffer' => '/([a-z]+\/json$)/']);
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');

$firstContent = $response->getContent();
$secondContent = $response->getContent();

$this->assertSame($firstContent, $secondContent);
}

public function testPdfRegexBuffer(): void
{
$client = new CurlHttpClient(['buffer' => '/application\/pdf$/']);
$response = $client->request('GET', 'http://s2.q4cdn.com/235752014/files/doc_downloads/test.pdf');

$firstContent = $response->getContent();
$secondContent = $response->getContent();

$this->assertSame($response->getContent(false), $response->getContent(false));
$this->assertSame($firstContent, $secondContent);
}

/**
* @expectedException \Symfony\Component\HttpClient\Exception\TransportException
*/
public function testBufferForImagesWithFalseBuffer(): void
public function testFalseBuffer(): void
{
$client = new CurlHttpClient(['buffer' => false]);
$response = $client->request('GET', 'http://s2.q4cdn.com/235752014/files/doc_downloads/test.pdf');
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');

$pdf = $response->getContent(false);
$secondPdf = $response->getContent(false);
$firstPosts = $response->getContent();
$secondPosts = $response->getContent();
}

public function testBufferForImagesWithTrueBuffer(): void
public function testTrueBuffer(): void
{
$client = new CurlHttpClient(['buffer' => true]);
$response = $client->request('GET', 'http://s2.q4cdn.com/235752014/files/doc_downloads/test.pdf');
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');

$pdf = $response->getContent(false);
$secondPdf = $response->getContent(false);
$firstContent = $response->getContent();
$secondContent = $response->getContent();

$this->assertSame($pdf, $secondPdf);
$this->assertSame($firstContent, $secondContent);
}
}
3 changes: 3 additions & 0 deletions src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php
Expand Up @@ -122,6 +122,9 @@ protected function getHttpClient(string $testCase): HttpClientInterface
case 'testUncheckedTimeoutThrows':
$body = ['<1>', '', '<2>'];
$responses[] = new MockResponse($body, ['response_headers' => $headers]);
break;
case 'testBufferRegex':

break;
}

Expand Down
45 changes: 45 additions & 0 deletions src/Symfony/Component/HttpClient/Tests/NativeHttpClientTest.php
Expand Up @@ -20,4 +20,49 @@ protected function getHttpClient(string $testCase): HttpClientInterface
{
return new NativeHttpClient();
}

public function testJsonRegexBuffer(): void
{
$client = new NativeHttpClient(['buffer' => '/([a-z]+\/json$)/']);
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');

$firstContent = $response->getContent();
$secondContent = $response->getContent();

$this->assertSame($firstContent, $secondContent);
}

public function testPdfRegexBuffer(): void
{
$client = new NativeHttpClient(['buffer' => '/application\/pdf$/']);
$response = $client->request('GET', 'http://s2.q4cdn.com/235752014/files/doc_downloads/test.pdf');

$firstContent = $response->getContent();
$secondContent = $response->getContent();

$this->assertSame($firstContent, $secondContent);
}

/**
* @expectedException \Symfony\Component\HttpClient\Exception\TransportException
*/
public function testFalseBuffer(): void
{
$client = new NativeHttpClient(['buffer' => false]);
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');

$firstPosts = $response->getContent();
$secondPosts = $response->getContent();
}

public function testTrueBuffer(): void
{
$client = new NativeHttpClient(['buffer' => true]);
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/users');

$firstContent = $response->getContent();
$secondContent = $response->getContent();

$this->assertSame($firstContent, $secondContent);
}
}

0 comments on commit f4ddd10

Please sign in to comment.