Repository: googleapis/google-http-java-client
Pull request #1608 (2022-03-23 22:30:43)

fix: `Content-Encoding: gzip` along with `Transfer-Encoding: chunked` sometimes terminates early

#### The issue
When `GZIPInputStream` completes processing an individual member it will call `InputStream#available()`
to determine if there is more stream to try and process. If the call to `available()` returns 0
`GZIPInputStream` will determine it has processed the entirety of the underlying stream. This is
spurious, as `InputStream#available()` is allowed to return 0 if it would require blocking in order
for more bytes to be available. When `GZIPInputStream` is reading from a `Transfer-Encoding: chunked`
response, if the chunk boundary happens to align closely enough to the member boundary
`GZIPInputStream` won't consume the whole response.

#### The fix
Add new `OptimisticAvailabilityInputStream`, which provides an optimistic "estimate" of the number of
`available()` bytes in the underlying stream. When instantiating a `GZIPInputStream` for a response,
automatically decorate the provided `InputStream` with an `OptimisticAvailabilityInputStream`.

#### Verification
This scenario isn't unique to processing of chunked responses, and can be replicated reliably using
a `java.io.SequenceInputStream` with two underlying `java.io.ByteArrayInputStream`. See
GzipSupportTest.java for a reproduction.

The need for this class has been verified for the following JVMs:
* ```
  openjdk version "1.8.0_292"
  OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_292-b10)
  OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.292-b10, mixed mode)
  ```
* ```
  openjdk version "11.0.14.1" 2022-02-08
  OpenJDK Runtime Environment Temurin-11.0.14.1+1 (build 11.0.14.1+1)
  OpenJDK 64-Bit Server VM Temurin-11.0.14.1+1 (build 11.0.14.1+1, mixed mode)
  ```
* ```
  openjdk version "17" 2021-09-14
  OpenJDK Runtime Environment Temurin-17+35 (build 17+35)
  OpenJDK 64-Bit Server VM Temurin-17+35 (build 17+35, mixed mode, sharing)
  ```



Patch:
diff --git a/.github/workflows/downstream.yaml b/.github/workflows/downstream.yaml
index 3d372926..1366d24d 100644
--- a/.github/workflows/downstream.yaml
+++ b/.github/workflows/downstream.yaml
@@ -133,10 +133,12 @@ jobs:
         - workflow-executions
         - workflows
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v1
+    - uses: actions/checkout@v2
+    - uses: actions/setup-java@v3
       with:
+        distribution: zulu
         java-version: ${{matrix.java}}
     - run: java -version
+    - run: sudo apt-get update -y
     - run: sudo apt-get install libxml2-utils
     - run: .kokoro/downstream-client-library-check.sh google-http-client-bom ${{matrix.repo}}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a326fa60..03f5a60d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,19 @@
 # Changelog
 
+### [1.41.5](https://github.com/googleapis/google-http-java-client/compare/v1.41.4...v1.41.5) (2022-03-21)
+
+
+### Documentation
+
+* **deps:** libraries-bom 24.4.0 release ([#1596](https://github.com/googleapis/google-http-java-client/issues/1596)) ([327fe12](https://github.com/googleapis/google-http-java-client/commit/327fe12a122ebb4022a2da55694217233a2badaf))
+
+
+### Dependencies
+
+* update actions/checkout action to v3 ([#1593](https://github.com/googleapis/google-http-java-client/issues/1593)) ([92002c0](https://github.com/googleapis/google-http-java-client/commit/92002c07d60b738657383e2484f56abc1cde6920))
+* update dependency com.fasterxml.jackson.core:jackson-core to v2.13.2 ([#1598](https://github.com/googleapis/google-http-java-client/issues/1598)) ([41ac833](https://github.com/googleapis/google-http-java-client/commit/41ac833249e18cbbd304f825b12202e51bebec85))
+* update project.appengine.version to v2 (major) ([#1597](https://github.com/googleapis/google-http-java-client/issues/1597)) ([c06cf95](https://github.com/googleapis/google-http-java-client/commit/c06cf95f9b1be77e2229c3b2f78ece0789eaec15))
+
 ### [1.41.4](https://github.com/googleapis/google-http-java-client/compare/v1.41.3...v1.41.4) (2022-02-11)
 
 
diff --git a/google-http-client-android/pom.xml b/google-http-client-android/pom.xml
index 3450e786..0278df84 100644
--- a/google-http-client-android/pom.xml
+++ b/google-http-client-android/pom.xml
@@ -4,11 +4,11 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../pom.xml</relativePath>
   </parent>
   <artifactId>google-http-client-android</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-android:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-android:current} -->
   <name>Android Platform Extensions to the Google HTTP Client Library for Java.</name>
 
   <build>
diff --git a/google-http-client-apache-v2/pom.xml b/google-http-client-apache-v2/pom.xml
index c6694a0a..542c6e0f 100644
--- a/google-http-client-apache-v2/pom.xml
+++ b/google-http-client-apache-v2/pom.xml
@@ -4,11 +4,11 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../pom.xml</relativePath>
   </parent>
   <artifactId>google-http-client-apache-v2</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-apache-v2:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-apache-v2:current} -->
   <name>Apache HTTP transport v2 for the Google HTTP Client Library for Java.</name>
 
   <build>
diff --git a/google-http-client-appengine/pom.xml b/google-http-client-appengine/pom.xml
index 75e2427b..814bb715 100644
--- a/google-http-client-appengine/pom.xml
+++ b/google-http-client-appengine/pom.xml
@@ -4,11 +4,11 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../pom.xml</relativePath>
   </parent>
   <artifactId>google-http-client-appengine</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-appengine:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-appengine:current} -->
   <name>Google App Engine extensions to the Google HTTP Client Library for Java.</name>
 
   <build>
diff --git a/google-http-client-assembly/pom.xml b/google-http-client-assembly/pom.xml
index 572531f6..af10fe95 100644
--- a/google-http-client-assembly/pom.xml
+++ b/google-http-client-assembly/pom.xml
@@ -4,12 +4,12 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../pom.xml</relativePath>
   </parent>
   <groupId>com.google.http-client</groupId>
   <artifactId>google-http-client-assembly</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-assembly:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-assembly:current} -->
   <packaging>pom</packaging>
   <name>Assembly for the Google HTTP Client Library for Java</name>
 
diff --git a/google-http-client-bom/pom.xml b/google-http-client-bom/pom.xml
index 839c2ec2..392e97c0 100644
--- a/google-http-client-bom/pom.xml
+++ b/google-http-client-bom/pom.xml
@@ -3,7 +3,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.http-client</groupId>
   <artifactId>google-http-client-bom</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-bom:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-bom:current} -->
   <packaging>pom</packaging>
 
   <name>Google HTTP Client Library for Java BOM</name>
@@ -63,52 +63,52 @@
       <dependency>
         <groupId>com.google.http-client</groupId>
         <artifactId>google-http-client</artifactId>
-        <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client:current} -->
+        <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.http-client</groupId>
         <artifactId>google-http-client-android</artifactId>
-        <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-android:current} -->
+        <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-android:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.http-client</groupId>
         <artifactId>google-http-client-apache-v2</artifactId>
-        <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-apache-v2:current} -->
+        <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-apache-v2:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.http-client</groupId>
         <artifactId>google-http-client-appengine</artifactId>
-        <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-appengine:current} -->
+        <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-appengine:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.http-client</groupId>
         <artifactId>google-http-client-findbugs</artifactId>
-        <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-findbugs:current} -->
+        <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-findbugs:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.http-client</groupId>
         <artifactId>google-http-client-gson</artifactId>
-        <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-gson:current} -->
+        <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-gson:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.http-client</groupId>
         <artifactId>google-http-client-jackson2</artifactId>
-        <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-jackson2:current} -->
+        <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-jackson2:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.http-client</groupId>
         <artifactId>google-http-client-protobuf</artifactId>
-        <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-protobuf:current} -->
+        <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-protobuf:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.http-client</groupId>
         <artifactId>google-http-client-test</artifactId>
-        <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-test:current} -->
+        <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-test:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.http-client</groupId>
         <artifactId>google-http-client-xml</artifactId>
-        <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-xml:current} -->
+        <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-xml:current} -->
       </dependency>
     </dependencies>
   </dependencyManagement>
diff --git a/google-http-client-findbugs/pom.xml b/google-http-client-findbugs/pom.xml
index 268d2366..cb86215f 100644
--- a/google-http-client-findbugs/pom.xml
+++ b/google-http-client-findbugs/pom.xml
@@ -4,11 +4,11 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../pom.xml</relativePath>
   </parent>
   <artifactId>google-http-client-findbugs</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-findbugs:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-findbugs:current} -->
   <name>Google APIs Client Library Findbugs custom plugin.</name>
 
   <build>
diff --git a/google-http-client-gson/pom.xml b/google-http-client-gson/pom.xml
index 210266a7..fb24ceea 100644
--- a/google-http-client-gson/pom.xml
+++ b/google-http-client-gson/pom.xml
@@ -4,11 +4,11 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../pom.xml</relativePath>
   </parent>
   <artifactId>google-http-client-gson</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-gson:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-gson:current} -->
   <name>GSON extensions to the Google HTTP Client Library for Java.</name>
 
   <build>
diff --git a/google-http-client-jackson2/pom.xml b/google-http-client-jackson2/pom.xml
index 743944aa..178641fc 100644
--- a/google-http-client-jackson2/pom.xml
+++ b/google-http-client-jackson2/pom.xml
@@ -4,11 +4,11 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../pom.xml</relativePath>
   </parent>
   <artifactId>google-http-client-jackson2</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-jackson2:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-jackson2:current} -->
   <name>Jackson 2 extensions to the Google HTTP Client Library for Java.</name>
 
   <build>
diff --git a/google-http-client-protobuf/pom.xml b/google-http-client-protobuf/pom.xml
index 6298f6f9..2810bd9f 100644
--- a/google-http-client-protobuf/pom.xml
+++ b/google-http-client-protobuf/pom.xml
@@ -4,11 +4,11 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../pom.xml</relativePath>
   </parent>
   <artifactId>google-http-client-protobuf</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-protobuf:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-protobuf:current} -->
   <name>Protocol Buffer extensions to the Google HTTP Client Library for Java.</name>
 
   <build>
diff --git a/google-http-client-xml/pom.xml b/google-http-client-xml/pom.xml
index 21d5bdbd..19f01e72 100644
--- a/google-http-client-xml/pom.xml
+++ b/google-http-client-xml/pom.xml
@@ -4,11 +4,11 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../pom.xml</relativePath>
   </parent>
   <artifactId>google-http-client-xml</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-xml:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-xml:current} -->
   <name>XML extensions to the Google HTTP Client Library for Java.</name>
 
   <build>
diff --git a/google-http-client/pom.xml b/google-http-client/pom.xml
index 5135c8cc..f519fec1 100644
--- a/google-http-client/pom.xml
+++ b/google-http-client/pom.xml
@@ -4,11 +4,11 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../pom.xml</relativePath>
   </parent>
   <artifactId>google-http-client</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client:current} -->
   <name>Google HTTP Client Library for Java</name>
   <description>
     Google HTTP Client Library for Java. Functionality that works on all supported Java platforms,
diff --git a/google-http-client/src/main/java/com/google/api/client/http/GzipSupport.java b/google-http-client/src/main/java/com/google/api/client/http/GzipSupport.java
new file mode 100644
index 00000000..6dc5df30
--- /dev/null
+++ b/google-http-client/src/main/java/com/google/api/client/http/GzipSupport.java
@@ -0,0 +1,90 @@
+package com.google.api.client.http;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+
+final class GzipSupport {
+
+  private GzipSupport() {}
+
+  static GZIPInputStream newGzipInputStream(InputStream in) throws IOException {
+    return new GZIPInputStream(new OptimisticAvailabilityInputStream(in));
+  }
+
+  /**
+   * When {@link GZIPInputStream} completes processing an individual member it will call {@link
+   * InputStream#available()} to determine if there is more stream to try and process. If the call
+   * to {@code available()} returns 0 {@code GZIPInputStream} will determine it has processed the
+   * entirety of the underlying stream. This is spurious, as {@link InputStream#available()} is
+   * allowed to return 0 if it would require blocking in order for more bytes to be available. When
+   * {@code GZIPInputStream} is reading from a {@code Transfer-Encoding: chunked} response, if the
+   * chunk boundary happens to align closely enough to the member boundary {@code GZIPInputStream}
+   * won't consume the whole response.
+   *
+   * <p>This class, provides an optimistic "estimate" (in actuality, a lie) of the number of {@code
+   * available()} bytes in the underlying stream. It does this by tracking the last number of bytes
+   * read. If the last number of bytes read is grater than -1, we return {@link Integer#MAX_VALUE}
+   * to any call of {@link #available()}.
+   *
+   * <p>We're breaking the contract of available() in that we're lying about how much data we have
+   * accessible without blocking, however in the case where we're weaving {@link GZIPInputStream}
+   * into response processing we already know there are going to be blocking calls to read before
+   * the stream is exhausted.
+   *
+   * <p>This scenario isn't unique to processing of chunked responses, and can be replicated
+   * reliably using a {@link java.io.SequenceInputStream} with two underlying {@link
+   * java.io.ByteArrayInputStream}. See the corresponding test class for a reproduction.
+   *
+   * <p>The need for this class has been verified for the following JVMs:
+   *
+   * <ol>
+   *   <li>
+   *       <pre>
+   * openjdk version "1.8.0_292"
+   * OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_292-b10)
+   * OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.292-b10, mixed mode)
+   *   </pre>
+   *   <li>
+   *       <pre>
+   * openjdk version "11.0.14.1" 2022-02-08
+   * OpenJDK Runtime Environment Temurin-11.0.14.1+1 (build 11.0.14.1+1)
+   * OpenJDK 64-Bit Server VM Temurin-11.0.14.1+1 (build 11.0.14.1+1, mixed mode)
+   *   </pre>
+   *   <li>
+   *       <pre>
+   * openjdk version "17" 2021-09-14
+   * OpenJDK Runtime Environment Temurin-17+35 (build 17+35)
+   * OpenJDK 64-Bit Server VM Temurin-17+35 (build 17+35, mixed mode, sharing)
+   *   </pre>
+   * </ol>
+   */
+  private static final class OptimisticAvailabilityInputStream extends FilterInputStream {
+    private int lastRead = 0;
+
+    OptimisticAvailabilityInputStream(InputStream delegate) {
+      super(delegate);
+    }
+
+    @Override
+    public int available() throws IOException {
+      return lastRead > -1 ? Integer.MAX_VALUE : 0;
+    }
+
+    @Override
+    public int read() throws IOException {
+      return lastRead = super.read();
+    }
+
+    @Override
+    public int read(byte[] b) throws IOException {
+      return lastRead = super.read(b);
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+      return lastRead = super.read(b, off, len);
+    }
+  }
+}
diff --git a/google-http-client/src/main/java/com/google/api/client/http/HttpResponse.java b/google-http-client/src/main/java/com/google/api/client/http/HttpResponse.java
index e9794321..13020867 100644
--- a/google-http-client/src/main/java/com/google/api/client/http/HttpResponse.java
+++ b/google-http-client/src/main/java/com/google/api/client/http/HttpResponse.java
@@ -30,7 +30,6 @@ import java.nio.charset.StandardCharsets;
 import java.util.Locale;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import java.util.zip.GZIPInputStream;
 
 /**
  * HTTP response.
@@ -362,7 +361,7 @@ public final class HttpResponse {
               // GZIPInputStream.close() --> ConsumingInputStream.close() -->
               // exhaust(ConsumingInputStream)
               lowLevelResponseContent =
-                  new GZIPInputStream(new ConsumingInputStream(lowLevelResponseContent));
+                  GzipSupport.newGzipInputStream(new ConsumingInputStream(lowLevelResponseContent));
             }
           }
           // logging (wrap content with LoggingInputStream)
diff --git a/pom.xml b/pom.xml
index 518cccd2..5bf1b762 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.http-client</groupId>
   <artifactId>google-http-client-parent</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
   <packaging>pom</packaging>
   <name>Parent for the Google HTTP Client Library for Java</name>
   <description>Google HTTP Client Library for Java</description>
@@ -560,7 +560,7 @@
       - google-api-java-client/google-api-client-assembly/android-properties (make the filenames match the version here)
       - Internally, update the default features.json file
     -->
-    <project.http-client.version>1.41.5-SNAPSHOT</project.http-client.version><!-- {x-version-update:google-http-client-parent:current} -->
+    <project.http-client.version>1.41.6-SNAPSHOT</project.http-client.version><!-- {x-version-update:google-http-client-parent:current} -->
     <project.appengine.version>2.0.4</project.appengine.version>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <project.jsr305.version>3.0.2</project.jsr305.version>
diff --git a/samples/dailymotion-simple-cmdline-sample/pom.xml b/samples/dailymotion-simple-cmdline-sample/pom.xml
index 4b6035a0..96b4c8d0 100644
--- a/samples/dailymotion-simple-cmdline-sample/pom.xml
+++ b/samples/dailymotion-simple-cmdline-sample/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../../pom.xml</relativePath>
   </parent>
   <artifactId>dailymotion-simple-cmdline-sample</artifactId>
diff --git a/versions.txt b/versions.txt
index 00fdc7c9..b94bfbde 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,17 +1,17 @@
 # Format:
 # module:released-version:current-version
 
-google-http-client:1.41.4:1.41.5-SNAPSHOT
-google-http-client-bom:1.41.4:1.41.5-SNAPSHOT
-google-http-client-parent:1.41.4:1.41.5-SNAPSHOT
-google-http-client-android:1.41.4:1.41.5-SNAPSHOT
-google-http-client-android-test:1.41.4:1.41.5-SNAPSHOT
-google-http-client-apache-v2:1.41.4:1.41.5-SNAPSHOT
-google-http-client-appengine:1.41.4:1.41.5-SNAPSHOT
-google-http-client-assembly:1.41.4:1.41.5-SNAPSHOT
-google-http-client-findbugs:1.41.4:1.41.5-SNAPSHOT
-google-http-client-gson:1.41.4:1.41.5-SNAPSHOT
-google-http-client-jackson2:1.41.4:1.41.5-SNAPSHOT
-google-http-client-protobuf:1.41.4:1.41.5-SNAPSHOT
-google-http-client-test:1.41.4:1.41.5-SNAPSHOT
-google-http-client-xml:1.41.4:1.41.5-SNAPSHOT
+google-http-client:1.41.5:1.41.6-SNAPSHOT
+google-http-client-bom:1.41.5:1.41.6-SNAPSHOT
+google-http-client-parent:1.41.5:1.41.6-SNAPSHOT
+google-http-client-android:1.41.5:1.41.6-SNAPSHOT
+google-http-client-android-test:1.41.5:1.41.6-SNAPSHOT
+google-http-client-apache-v2:1.41.5:1.41.6-SNAPSHOT
+google-http-client-appengine:1.41.5:1.41.6-SNAPSHOT
+google-http-client-assembly:1.41.5:1.41.6-SNAPSHOT
+google-http-client-findbugs:1.41.5:1.41.6-SNAPSHOT
+google-http-client-gson:1.41.5:1.41.6-SNAPSHOT
+google-http-client-jackson2:1.41.5:1.41.6-SNAPSHOT
+google-http-client-protobuf:1.41.5:1.41.6-SNAPSHOT
+google-http-client-test:1.41.5:1.41.6-SNAPSHOT
+google-http-client-xml:1.41.5:1.41.6-SNAPSHOT


Test patch:
diff --git a/google-http-client-android-test/pom.xml b/google-http-client-android-test/pom.xml
index cb7c239e..d9741e5c 100644
--- a/google-http-client-android-test/pom.xml
+++ b/google-http-client-android-test/pom.xml
@@ -4,7 +4,7 @@
   <groupId>google-http-client</groupId>
   <artifactId>google-http-client-android-test</artifactId>
   <name>Test project for google-http-client-android.</name>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-android-test:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-android-test:current} -->
   <packaging>apk</packaging>
 
   <build>
@@ -53,7 +53,7 @@
     <dependency>
       <groupId>com.google.http-client</groupId>
       <artifactId>google-http-client-android</artifactId>
-      <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-android:current} -->
+      <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-android:current} -->
       <exclusions>
         <exclusion>
           <artifactId>android</artifactId>
@@ -72,7 +72,7 @@
     <dependency>
       <groupId>com.google.http-client</groupId>
       <artifactId>google-http-client-test</artifactId>
-      <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-test:current} -->
+      <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-test:current} -->
       <exclusions>
         <exclusion>
           <artifactId>junit</artifactId>
diff --git a/google-http-client-test/pom.xml b/google-http-client-test/pom.xml
index 44a0526c..3d049edc 100644
--- a/google-http-client-test/pom.xml
+++ b/google-http-client-test/pom.xml
@@ -4,11 +4,11 @@
   <parent>
     <groupId>com.google.http-client</groupId>
     <artifactId>google-http-client-parent</artifactId>
-    <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
+    <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-parent:current} -->
     <relativePath>../pom.xml</relativePath>
   </parent>
   <artifactId>google-http-client-test</artifactId>
-  <version>1.41.5-SNAPSHOT</version><!-- {x-version-update:google-http-client-test:current} -->
+  <version>1.41.6-SNAPSHOT</version><!-- {x-version-update:google-http-client-test:current} -->
   <name>Shared classes used for testing of artifacts in the Google HTTP Client Library for Java.</name>
 
   <build>
diff --git a/google-http-client/src/test/java/com/google/api/client/http/GzipSupportTest.java b/google-http-client/src/test/java/com/google/api/client/http/GzipSupportTest.java
new file mode 100644
index 00000000..f7c86322
--- /dev/null
+++ b/google-http-client/src/test/java/com/google/api/client/http/GzipSupportTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.api.client.http;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.io.ByteStreams;
+import com.google.common.io.CountingInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+import java.util.zip.GZIPInputStream;
+import org.junit.Test;
+
+public final class GzipSupportTest {
+
+  @SuppressWarnings("UnstableApiUsage") // CountingInputStream is @Beta
+  @Test
+  public void gzipInputStreamConsumesAllBytes() throws IOException {
+    byte[] data = new byte[] {(byte) 'a', (byte) 'b'};
+    // `echo -n a > a.txt && gzip -n9 a.txt`
+    byte[] member0 =
+        new byte[] {
+          0x1f,
+          (byte) 0x8b,
+          0x08,
+          0x00,
+          0x00,
+          0x00,
+          0x00,
+          0x00,
+          0x02,
+          0x03,
+          0x4b,
+          0x04,
+          0x00,
+          (byte) 0x43,
+          (byte) 0xbe,
+          (byte) 0xb7,
+          (byte) 0xe8,
+          0x01,
+          0x00,
+          0x00,
+          0x00
+        };
+    // `echo -n b > b.txt && gzip -n9 b.txt`
+    byte[] member1 =
+        new byte[] {
+          0x1f,
+          (byte) 0x8b,
+          0x08,
+          0x00,
+          0x00,
+          0x00,
+          0x00,
+          0x00,
+          0x02,
+          0x03,
+          0x4b,
+          0x02,
+          0x00,
+          (byte) 0xf9,
+          (byte) 0xef,
+          (byte) 0xbe,
+          (byte) 0x71,
+          0x01,
+          0x00,
+          0x00,
+          0x00
+        };
+    int totalZippedBytes = member0.length + member1.length;
+    try (InputStream s =
+            new SequenceInputStream(
+                new ByteArrayInputStream(member0), new ByteArrayInputStream(member1));
+        CountingInputStream countS = new CountingInputStream(s);
+        GZIPInputStream g = GzipSupport.newGzipInputStream(countS);
+        CountingInputStream countG = new CountingInputStream(g)) {
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      ByteStreams.copy(countG, baos);
+      assertThat(baos.toByteArray()).isEqualTo(data);
+      assertThat(countG.getCount()).isEqualTo(data.length);
+      assertThat(countS.getCount()).isEqualTo(totalZippedBytes);
+    }
+  }
+}