1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Symfony\Component\HttpFoundation\Tests;
13:
14: use Symfony\Component\HttpFoundation\BinaryFileResponse;
15: use Symfony\Component\HttpFoundation\Request;
16: use Symfony\Component\HttpFoundation\ResponseHeaderBag;
17: use Symfony\Component\HttpFoundation\Tests\File\FakeFile;
18:
19: class BinaryFileResponseTest extends ResponseTestCase
20: {
21: public function testConstruction()
22: {
23: $file = __DIR__.'/../README.md';
24: $response = new BinaryFileResponse($file, 404, array('X-Header' => 'Foo'), true, null, true, true);
25: $this->assertEquals(404, $response->getStatusCode());
26: $this->assertEquals('Foo', $response->headers->get('X-Header'));
27: $this->assertTrue($response->headers->has('ETag'));
28: $this->assertTrue($response->headers->has('Last-Modified'));
29: $this->assertFalse($response->headers->has('Content-Disposition'));
30:
31: $response = BinaryFileResponse::create($file, 404, array(), true, ResponseHeaderBag::DISPOSITION_INLINE);
32: $this->assertEquals(404, $response->getStatusCode());
33: $this->assertFalse($response->headers->has('ETag'));
34: $this->assertEquals('inline; filename="README.md"', $response->headers->get('Content-Disposition'));
35: }
36:
37: 38: 39:
40: public function testSetContent()
41: {
42: $response = new BinaryFileResponse(__FILE__);
43: $response->setContent('foo');
44: }
45:
46: public function testGetContent()
47: {
48: $response = new BinaryFileResponse(__FILE__);
49: $this->assertFalse($response->getContent());
50: }
51:
52: 53: 54:
55: public function testRequests($requestRange, $offset, $length, $responseRange)
56: {
57: $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag();
58:
59:
60: $request = Request::create('/');
61: $response->prepare($request);
62: $etag = $response->headers->get('ETag');
63:
64:
65: $request = Request::create('/');
66: $request->headers->set('If-Range', $etag);
67: $request->headers->set('Range', $requestRange);
68:
69: $file = fopen(__DIR__.'/File/Fixtures/test.gif', 'r');
70: fseek($file, $offset);
71: $data = fread($file, $length);
72: fclose($file);
73:
74: $this->expectOutputString($data);
75: $response = clone $response;
76: $response->prepare($request);
77: $response->sendContent();
78:
79: $this->assertEquals(206, $response->getStatusCode());
80: $this->assertEquals($responseRange, $response->headers->get('Content-Range'));
81: }
82:
83: public function provideRanges()
84: {
85: return array(
86: array('bytes=1-4', 1, 4, 'bytes 1-4/35'),
87: array('bytes=-5', 30, 5, 'bytes 30-34/35'),
88: array('bytes=30-', 30, 5, 'bytes 30-34/35'),
89: array('bytes=30-30', 30, 1, 'bytes 30-30/35'),
90: array('bytes=30-34', 30, 5, 'bytes 30-34/35'),
91: );
92: }
93:
94: 95: 96:
97: public function testFullFileRequests($requestRange)
98: {
99: $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag();
100:
101:
102: $request = Request::create('/');
103: $request->headers->set('Range', $requestRange);
104:
105: $file = fopen(__DIR__.'/File/Fixtures/test.gif', 'r');
106: $data = fread($file, 35);
107: fclose($file);
108:
109: $this->expectOutputString($data);
110: $response = clone $response;
111: $response->prepare($request);
112: $response->sendContent();
113:
114: $this->assertEquals(200, $response->getStatusCode());
115: }
116:
117: public function provideFullFileRanges()
118: {
119: return array(
120: array('bytes=0-'),
121: array('bytes=0-34'),
122: array('bytes=-35'),
123:
124: array('bytes=20-10'),
125: array('bytes=50-40'),
126: );
127: }
128:
129: 130: 131:
132: public function testInvalidRequests($requestRange)
133: {
134: $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag();
135:
136:
137: $request = Request::create('/');
138: $request->headers->set('Range', $requestRange);
139:
140: $response = clone $response;
141: $response->prepare($request);
142: $response->sendContent();
143:
144: $this->assertEquals(416, $response->getStatusCode());
145:
146: }
147:
148: public function provideInvalidRanges()
149: {
150: return array(
151: array('bytes=-40'),
152: array('bytes=30-40'),
153: );
154: }
155:
156: public function testXSendfile()
157: {
158: $request = Request::create('/');
159: $request->headers->set('X-Sendfile-Type', 'X-Sendfile');
160:
161: BinaryFileResponse::trustXSendfileTypeHeader();
162: $response = BinaryFileResponse::create(__DIR__.'/../README.md');
163: $response->prepare($request);
164:
165: $this->expectOutputString('');
166: $response->sendContent();
167:
168: $this->assertContains('README.md', $response->headers->get('X-Sendfile'));
169: }
170:
171: 172: 173:
174: public function testXAccelMapping($realpath, $mapping, $virtual)
175: {
176: $request = Request::create('/');
177: $request->headers->set('X-Sendfile-Type', 'X-Accel-Redirect');
178: $request->headers->set('X-Accel-Mapping', $mapping);
179:
180: $file = new FakeFile($realpath, __DIR__.'/File/Fixtures/test');
181:
182: BinaryFileResponse::trustXSendFileTypeHeader();
183: $response = new BinaryFileResponse($file);
184: $reflection = new \ReflectionObject($response);
185: $property = $reflection->getProperty('file');
186: $property->setAccessible(true);
187: $property->setValue($response, $file);
188:
189: $response->prepare($request);
190: $this->assertEquals($virtual, $response->headers->get('X-Accel-Redirect'));
191: }
192:
193: public function testDeleteFileAfterSend()
194: {
195: $request = Request::create('/');
196:
197: $path = __DIR__.'/File/Fixtures/to_delete';
198: touch($path);
199: $realPath = realpath($path);
200: $this->assertFileExists($realPath);
201:
202: $response = new BinaryFileResponse($realPath);
203: $response->deleteFileAfterSend(true);
204:
205: $response->prepare($request);
206: $response->sendContent();
207:
208: $this->assertFileNotExists($path);
209: }
210:
211: public function testAcceptRangeOnUnsafeMethods()
212: {
213: $request = Request::create('/', 'POST');
214: $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif');
215: $response->prepare($request);
216:
217: $this->assertEquals('none', $response->headers->get('Accept-Ranges'));
218: }
219:
220: public function testAcceptRangeNotOverriden()
221: {
222: $request = Request::create('/', 'POST');
223: $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif');
224: $response->headers->set('Accept-Ranges', 'foo');
225: $response->prepare($request);
226:
227: $this->assertEquals('foo', $response->headers->get('Accept-Ranges'));
228: }
229:
230: public function getSampleXAccelMappings()
231: {
232: return array(
233: array('/var/www/var/www/files/foo.txt', '/files/=/var/www/', '/files/var/www/files/foo.txt'),
234: array('/home/foo/bar.txt', '/files/=/var/www/,/baz/=/home/foo/', '/baz/bar.txt'),
235: );
236: }
237:
238: protected function provideResponse()
239: {
240: return new BinaryFileResponse(__DIR__.'/../README.md');
241: }
242:
243: public static function tearDownAfterClass()
244: {
245: $path = __DIR__.'/../Fixtures/to_delete';
246: if (file_exists($path)) {
247: @unlink($path);
248: }
249: }
250: }
251: