Browse Source

Fix file response conversions.

The toCake() conversion did not convert files properly.
Mark Story 9 years ago
parent
commit
ca8722399c

+ 14 - 6
src/Http/ResponseTransformer.php

@@ -38,12 +38,17 @@ class ResponseTransformer
      */
     public static function toCake(PsrResponse $response)
     {
+        $body = static::getBody($response);
         $data = [
             'status' => $response->getStatusCode(),
-            'body' => static::getBody($response),
+            'body' => $body['body'],
         ];
         $cake = new CakeResponse($data);
-        foreach (static::parseCookies($response->getHeader('Set-Cookie')) as $cookie) {
+        if ($body['file']) {
+            $cake->file($body['file']);
+        }
+        $cookies = static::parseCookies($response->getHeader('Set-Cookie'));
+        foreach ($cookies as $cookie) {
             $cake->cookie($cookie);
         }
         $cake->header(static::collapseHeaders($response));
@@ -54,16 +59,19 @@ class ResponseTransformer
      * Get the response body from a PSR7 Response.
      *
      * @param PsrResponse $response The response to convert.
-     * @return string The response body.
+     * @return array A hash of 'body' and 'file'
      */
     protected static function getBody(PsrResponse $response)
     {
         $stream = $response->getBody();
+        if ($stream->getMetadata('wrapper_type') === 'plainfile') {
+            return ['body' => '', 'file' => $stream->getMetadata('uri')];
+        }
         if ($stream->getSize() === 0) {
-            return '';
+            return ['body' => '', 'file' => false];
         }
         $stream->rewind();
-        return $stream->getContents();
+        return ['body' => $stream->getContents(), 'file' => false];
     }
 
     /**
@@ -195,7 +203,7 @@ class ResponseTransformer
     {
         $stream = 'php://memory';
         $body = $response->body();
-        if (is_string($body)) {
+        if (is_string($body) && strlen($body)) {
             $stream = new Stream('php://memory', 'wb');
             $stream->write($body);
             return $stream;

+ 22 - 0
tests/TestCase/Http/ResponseTransformerTest.php

@@ -18,6 +18,7 @@ use Cake\Http\ResponseTransformer;
 use Cake\Network\Response as CakeResponse;
 use Cake\TestSuite\TestCase;
 use Zend\Diactoros\Response as PsrResponse;
+use Zend\Diactoros\Stream;
 
 /**
  * Test case for the response transformer.
@@ -119,6 +120,27 @@ class ResponseTransformerTest extends TestCase
     }
 
     /**
+     * Test conversion with a file body.
+     *
+     * @return void
+     */
+    public function testToCakeFileStream()
+    {
+        $stream = new Stream('file://' . __FILE__, 'rb');
+        $psr = new PsrResponse($stream, 200, ['Content-Disposition' => 'attachment; filename="test.php"']);
+        $result = ResponseTransformer::toCake($psr);
+
+        $this->assertNotEmpty($result->getFile(), 'Should convert file responses.');
+
+        $headers = $result->header();
+        $this->assertArrayHasKey('Content-Length', $headers);
+        $this->assertArrayHasKey('Content-Disposition', $headers);
+        $this->assertArrayHasKey('Content-Transfer-Encoding', $headers);
+        $this->assertArrayHasKey('Accept-Ranges', $headers);
+        $this->assertEquals('attachment; filename="test.php"', $headers['Content-Disposition']);
+    }
+
+    /**
      * Test conversion getting cookies.
      *
      * @return void

+ 14 - 0
tests/TestCase/TestSuite/IntegrationTestCaseTest.php

@@ -746,6 +746,20 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     }
 
     /**
+     * Test sending file with psr7 stack
+     *
+     * @return void
+     */
+    public function testSendFileHttpServer()
+    {
+        DispatcherFactory::clear();
+        $this->useHttpServer(true);
+
+        $this->get('/posts/file');
+        $this->assertFileResponse(TEST_APP . 'TestApp' . DS . 'Controller' . DS . 'PostsController.php');
+    }
+
+    /**
      * Test that assertFile requires a response
      *
      * @expectedException PHPUnit_Framework_AssertionFailedError