Browse Source

Automatically decompress gzip response bodies when possible.

If gzinflate() exists and a gzip response body is encountered, the
response body should automatically be decompressed.
mark_story 11 years ago
parent
commit
af6208c9cc
2 changed files with 45 additions and 0 deletions
  1. 28 0
      src/Network/Http/Response.php
  2. 17 0
      tests/TestCase/Network/Http/ResponseTest.php

+ 28 - 0
src/Network/Http/Response.php

@@ -125,10 +125,38 @@ class Response extends Message {
  */
 	public function __construct($headers = [], $body = '') {
 		$this->_parseHeaders($headers);
+		if ($this->header('Content-Encoding') === 'gzip') {
+			$body = $this->_decodeGzipBody($body);
+		}
 		$this->_body = $body;
 	}
 
 /**
+ * Uncompress a gzip response.
+ *
+ * Looks for gzip signatures, and if gzinflate() exists,
+ * the body will be decompressed.
+ *
+ * @param string $body Gzip encoded body.
+ * @return string
+ * @throws \RuntimeException When attempting to decode gzip content without gzinflate.
+ */
+	protected function _decodeGzipBody($body) {
+		if (!function_exists('gzinflate')) {
+			throw \RuntimeException('Cannot decompress gzip response body without gzipinflate()');
+		}
+		$offset = 0;
+		// Look for gzip 'signature'
+		if (substr($body, 0, 2) === "\x1f\x8b") {
+			$offset = 2;
+		}
+		// Check the format byte
+		if (substr($body, $offset, 1) === "\x08") {
+			return gzinflate(substr($body, $offset + 8));
+		}
+	}
+
+/**
  * Parses headers if necessary.
  *
  * - Decodes the status code.

+ 17 - 0
tests/TestCase/Network/Http/ResponseTest.php

@@ -278,4 +278,21 @@ XML;
 		$this->assertEquals('ISO-8859-1', $response->encoding());
 	}
 
+/**
+ * Test that gzip responses are automatically decompressed.
+ *
+ * @return void
+ */
+	public function testAutoDecodeGzipBody() {
+		$headers = [
+			'HTTP/1.0 200 OK',
+			'Content-Encoding: gzip',
+			'Content-Length: 32',
+			'Content-Type: text/html; charset=UTF-8'
+		];
+		$body = base64_decode('H4sIAAAAAAAAA/NIzcnJVyjPL8pJUQQAlRmFGwwAAAA=');
+		$response = new Response($headers, $body);
+		$this->assertEquals('Hello world!', $response->body);
+	}
+
 }