This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php
Fabien Potencier 51a71ab74a Merge branch '2.3' into 2.7
* 2.3:
  #17676 - making the proxy instantiation compatible with ProxyManager 2.x by detecting proxy features
  Fix bug when using an private aliased factory service
  ChoiceFormField of type "select" could be "disabled"
  Update contributing docs
  [Console] Fix escaping of trailing backslashes
  Fix constraint validator alias being required
  [ci] clone with depth=1 to kill push-forced PRs
  Add check on If-Range header
2016-02-28 17:19:47 +01:00

312 lines
11 KiB
PHP

<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpFoundation\Tests;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\Tests\File\FakeFile;
class BinaryFileResponseTest extends ResponseTestCase
{
public function testConstruction()
{
$file = __DIR__.'/../README.md';
$response = new BinaryFileResponse($file, 404, array('X-Header' => 'Foo'), true, null, true, true);
$this->assertEquals(404, $response->getStatusCode());
$this->assertEquals('Foo', $response->headers->get('X-Header'));
$this->assertTrue($response->headers->has('ETag'));
$this->assertTrue($response->headers->has('Last-Modified'));
$this->assertFalse($response->headers->has('Content-Disposition'));
$response = BinaryFileResponse::create($file, 404, array(), true, ResponseHeaderBag::DISPOSITION_INLINE);
$this->assertEquals(404, $response->getStatusCode());
$this->assertFalse($response->headers->has('ETag'));
$this->assertEquals('inline; filename="README.md"', $response->headers->get('Content-Disposition'));
}
/**
* @expectedException \LogicException
*/
public function testSetContent()
{
$response = new BinaryFileResponse(__FILE__);
$response->setContent('foo');
}
public function testGetContent()
{
$response = new BinaryFileResponse(__FILE__);
$this->assertFalse($response->getContent());
}
/**
* @dataProvider provideRanges
*/
public function testRequests($requestRange, $offset, $length, $responseRange)
{
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'))->setAutoEtag();
// do a request to get the ETag
$request = Request::create('/');
$response->prepare($request);
$etag = $response->headers->get('ETag');
// prepare a request for a range of the testing file
$request = Request::create('/');
$request->headers->set('If-Range', $etag);
$request->headers->set('Range', $requestRange);
$file = fopen(__DIR__.'/File/Fixtures/test.gif', 'r');
fseek($file, $offset);
$data = fread($file, $length);
fclose($file);
$this->expectOutputString($data);
$response = clone $response;
$response->prepare($request);
$response->sendContent();
$this->assertEquals(206, $response->getStatusCode());
$this->assertEquals($responseRange, $response->headers->get('Content-Range'));
}
/**
* @dataProvider provideRanges
*/
public function testRequestsWithoutEtag($requestRange, $offset, $length, $responseRange)
{
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'));
// do a request to get the LastModified
$request = Request::create('/');
$response->prepare($request);
$lastModified = $response->headers->get('Last-Modified');
// prepare a request for a range of the testing file
$request = Request::create('/');
$request->headers->set('If-Range', $lastModified);
$request->headers->set('Range', $requestRange);
$file = fopen(__DIR__.'/File/Fixtures/test.gif', 'r');
fseek($file, $offset);
$data = fread($file, $length);
fclose($file);
$this->expectOutputString($data);
$response = clone $response;
$response->prepare($request);
$response->sendContent();
$this->assertEquals(206, $response->getStatusCode());
$this->assertEquals($responseRange, $response->headers->get('Content-Range'));
}
public function provideRanges()
{
return array(
array('bytes=1-4', 1, 4, 'bytes 1-4/35'),
array('bytes=-5', 30, 5, 'bytes 30-34/35'),
array('bytes=30-', 30, 5, 'bytes 30-34/35'),
array('bytes=30-30', 30, 1, 'bytes 30-30/35'),
array('bytes=30-34', 30, 5, 'bytes 30-34/35'),
);
}
public function testRangeRequestsWithoutLastModifiedDate()
{
// prevent auto last modified
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'), true, null, false, false);
// prepare a request for a range of the testing file
$request = Request::create('/');
$request->headers->set('If-Range', date('D, d M Y H:i:s').' GMT');
$request->headers->set('Range', 'bytes=1-4');
$this->expectOutputString(file_get_contents(__DIR__.'/File/Fixtures/test.gif'));
$response = clone $response;
$response->prepare($request);
$response->sendContent();
$this->assertEquals(200, $response->getStatusCode());
$this->assertNull($response->headers->get('Content-Range'));
}
/**
* @dataProvider provideFullFileRanges
*/
public function testFullFileRequests($requestRange)
{
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'))->setAutoEtag();
// prepare a request for a range of the testing file
$request = Request::create('/');
$request->headers->set('Range', $requestRange);
$file = fopen(__DIR__.'/File/Fixtures/test.gif', 'r');
$data = fread($file, 35);
fclose($file);
$this->expectOutputString($data);
$response = clone $response;
$response->prepare($request);
$response->sendContent();
$this->assertEquals(200, $response->getStatusCode());
}
public function provideFullFileRanges()
{
return array(
array('bytes=0-'),
array('bytes=0-34'),
array('bytes=-35'),
// Syntactical invalid range-request should also return the full resource
array('bytes=20-10'),
array('bytes=50-40'),
);
}
/**
* @dataProvider provideInvalidRanges
*/
public function testInvalidRequests($requestRange)
{
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'))->setAutoEtag();
// prepare a request for a range of the testing file
$request = Request::create('/');
$request->headers->set('Range', $requestRange);
$response = clone $response;
$response->prepare($request);
$response->sendContent();
$this->assertEquals(416, $response->getStatusCode());
#$this->assertEquals('', $response->headers->get('Content-Range'));
}
public function provideInvalidRanges()
{
return array(
array('bytes=-40'),
array('bytes=30-40'),
);
}
/**
* @dataProvider provideXSendfileFiles
*/
public function testXSendfile($file)
{
$request = Request::create('/');
$request->headers->set('X-Sendfile-Type', 'X-Sendfile');
BinaryFileResponse::trustXSendfileTypeHeader();
$response = BinaryFileResponse::create($file, 200, array('Content-Type' => 'application/octet-stream'));
$response->prepare($request);
$this->expectOutputString('');
$response->sendContent();
$this->assertContains('README.md', $response->headers->get('X-Sendfile'));
}
public function provideXSendfileFiles()
{
return array(
array(__DIR__.'/../README.md'),
array('file://'.__DIR__.'/../README.md'),
);
}
/**
* @dataProvider getSampleXAccelMappings
*/
public function testXAccelMapping($realpath, $mapping, $virtual)
{
$request = Request::create('/');
$request->headers->set('X-Sendfile-Type', 'X-Accel-Redirect');
$request->headers->set('X-Accel-Mapping', $mapping);
$file = new FakeFile($realpath, __DIR__.'/File/Fixtures/test');
BinaryFileResponse::trustXSendfileTypeHeader();
$response = new BinaryFileResponse($file, 200, array('Content-Type' => 'application/octet-stream'));
$reflection = new \ReflectionObject($response);
$property = $reflection->getProperty('file');
$property->setAccessible(true);
$property->setValue($response, $file);
$response->prepare($request);
$this->assertEquals($virtual, $response->headers->get('X-Accel-Redirect'));
}
public function testDeleteFileAfterSend()
{
$request = Request::create('/');
$path = __DIR__.'/File/Fixtures/to_delete';
touch($path);
$realPath = realpath($path);
$this->assertFileExists($realPath);
$response = new BinaryFileResponse($realPath, 200, array('Content-Type' => 'application/octet-stream'));
$response->deleteFileAfterSend(true);
$response->prepare($request);
$response->sendContent();
$this->assertFileNotExists($path);
}
public function testAcceptRangeOnUnsafeMethods()
{
$request = Request::create('/', 'POST');
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'));
$response->prepare($request);
$this->assertEquals('none', $response->headers->get('Accept-Ranges'));
}
public function testAcceptRangeNotOverriden()
{
$request = Request::create('/', 'POST');
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'));
$response->headers->set('Accept-Ranges', 'foo');
$response->prepare($request);
$this->assertEquals('foo', $response->headers->get('Accept-Ranges'));
}
public function getSampleXAccelMappings()
{
return array(
array('/var/www/var/www/files/foo.txt', '/var/www/=/files/', '/files/var/www/files/foo.txt'),
array('/home/foo/bar.txt', '/var/www/=/files/,/home/foo/=/baz/', '/baz/bar.txt'),
);
}
protected function provideResponse()
{
return new BinaryFileResponse(__DIR__.'/../README.md', 200, array('Content-Type' => 'application/octet-stream'));
}
public static function tearDownAfterClass()
{
$path = __DIR__.'/../Fixtures/to_delete';
if (file_exists($path)) {
@unlink($path);
}
}
}