浏览代码

Add Gzip handling to RemoteFilesystem

Jordi Boggiano 13 年之前
父节点
当前提交
f98bd971f2

+ 0 - 1
src/Composer/Downloader/FileDownloader.php

@@ -74,7 +74,6 @@ class FileDownloader implements DownloaderInterface
         $url = $this->processUrl($url);
 
         $this->rfs->copy($package->getSourceUrl(), $url, $fileName);
-        $this->io->write('');
 
         if (!file_exists($fileName)) {
             throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'

+ 33 - 11
src/Composer/Util/RemoteFilesystem.php

@@ -12,6 +12,7 @@
 
 namespace Composer\Util;
 
+use Composer\Composer;
 use Composer\IO\IOInterface;
 use Composer\Downloader\TransportException;
 
@@ -101,22 +102,39 @@ class RemoteFilesystem
         }
 
         $result = @file_get_contents($fileUrl, false, $ctx);
-        if (null !== $fileName) {
-            $result = @file_put_contents($fileName, $result) ? true : false;
-        }
 
         // fix for 5.4.0 https://bugs.php.net/bug.php?id=61336
         if (!empty($http_response_header[0]) && preg_match('{^HTTP/\S+ 404}i', $http_response_header[0])) {
             $result = false;
         }
 
+        // decode gzip
+        if (false !== $result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http') {
+            foreach ($http_response_header as $header) {
+                if (preg_match('{^content-encoding: *gzip *$}i', $header)) {
+                    if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
+                        $result = zlib_decode($result);
+                    } else {
+                        // work around issue with gzuncompress & co that do not work with all gzip checksums
+                        $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
+                    }
+                    break;
+                }
+            }
+        }
+
+        // handle copy command if download was successful
+        if (false !== $result && null !== $fileName) {
+            $result = (Boolean) @file_put_contents($fileName, $result);
+        }
+
         // avoid overriding if content was loaded by a sub-call to get()
         if (null === $this->result) {
             $this->result = $result;
         }
 
         if ($this->progress) {
-            $this->io->overwrite("    Downloading", false);
+            $this->io->write('');
         }
 
         if (false === $this->result) {
@@ -184,17 +202,21 @@ class RemoteFilesystem
         }
     }
 
-    protected function getOptionsForUrl($url)
+    protected function getOptionsForUrl($originUrl)
     {
-        $options = array();
-        if ($this->io->hasAuthorization($url)) {
-            $auth = $this->io->getAuthorization($url);
+        $options['http']['header'] = 'User-Agent: Composer/'.Composer::VERSION."\r\n";
+        if (extension_loaded('zlib')) {
+            $options['http']['header'] .= 'Accept-Encoding: gzip'."\r\n";
+        }
+
+        if ($this->io->hasAuthorization($originUrl)) {
+            $auth = $this->io->getAuthorization($originUrl);
             $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
-            $options['http'] = array('header' => "Authorization: Basic $authStr\r\n");
+            $options['http']['header'] .= "Authorization: Basic $authStr\r\n";
         } elseif (null !== $this->io->getLastUsername()) {
             $authStr = base64_encode($this->io->getLastUsername() . ':' . $this->io->getLastPassword());
-            $options['http'] = array('header' => "Authorization: Basic $authStr\r\n");
-            $this->io->setAuthorization($url, $this->io->getLastUsername(), $this->io->getLastPassword());
+            $options['http']['header'] .= "Authorization: Basic $authStr\r\n";
+            $this->io->setAuthorization($originUrl, $this->io->getLastUsername(), $this->io->getLastPassword());
         }
 
         return $options;

+ 2 - 1
tests/Composer/Test/Util/RemoteFilesystemTest.php

@@ -31,7 +31,8 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue(null))
         ;
 
-        $this->assertEquals(array(), $this->callGetOptionsForUrl($io, array('http://example.org')));
+        $res = $this->callGetOptionsForUrl($io, array('http://example.org'));
+        $this->assertTrue(isset($res['http']['header']) && false !== strpos($res['http']['header'], 'User-Agent'), 'getOptions must return an array with a header containing a User-Agent');
     }
 
     public function testGetOptionsForUrlWithAuthorization()