http-client-branch: HTTP/2 200 response headers should not be appended to the 100-continue response headers http-client-branch
authordfuchs
Fri, 23 Feb 2018 16:25:32 +0000
branchhttp-client-branch
changeset 56166 56c52d6417d1
parent 56165 8a6065d830b9
child 56167 96fa4f49a9ff
http-client-branch: HTTP/2 200 response headers should not be appended to the 100-continue response headers
src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java
src/java.net.http/share/classes/jdk/internal/net/http/Response.java
src/java.net.http/share/classes/jdk/internal/net/http/Stream.java
src/java.net.http/share/classes/jdk/internal/net/http/common/HttpHeadersImpl.java
test/jdk/java/net/httpclient/AsFileDownloadTest.java
test/jdk/java/net/httpclient/FlowAdapterSubscriberTest.java
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java	Thu Feb 22 17:33:21 2018 +0000
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java	Fri Feb 23 16:25:32 2018 +0000
@@ -1191,6 +1191,12 @@
         private static final Set<String> PSEUDO_HEADERS =
                 Set.of(":authority", ":method", ":path", ":scheme", ":status");
 
+        /**
+         * Called when END_HEADERS was received. This consumer may be invoked
+         * again after reset() is called, but for a whole new set of headers.
+         */
+        void reset() { }
+
         @Override
         public void onDecoded(CharSequence name, CharSequence value)
                 throws UncheckedIOException
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Response.java	Thu Feb 22 17:33:21 2018 +0000
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Response.java	Fri Feb 23 16:25:32 2018 +0000
@@ -64,7 +64,7 @@
              int statusCode,
              HttpClient.Version version,
              boolean isConnectResponse) {
-        this.headers = headers;
+        this.headers = ImmutableHeaders.of(headers);
         this.request = req;
         this.version = version;
         this.exchange = exchange;
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java	Thu Feb 22 17:33:21 2018 +0000
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java	Fri Feb 23 16:25:32 2018 +0000
@@ -113,8 +113,8 @@
 
     final Http2Connection connection;
     final HttpRequestImpl request;
-    final DecodingCallback rspHeadersConsumer;
-    HttpHeadersImpl responseHeaders;
+    final HeadersConsumer rspHeadersConsumer;
+    final HttpHeadersImpl responseHeaders;
     final HttpHeadersImpl requestPseudoHeaders;
     volatile HttpResponse.BodySubscriber<T> responseSubscriber;
     final HttpRequest.BodyPublisher requestPublisher;
@@ -232,7 +232,7 @@
     {
         try {
             Log.logTrace("Reading body on stream {0}", streamid);
-            BodySubscriber<T> bodySubscriber = handler.apply(responseCode, responseHeaders);
+            BodySubscriber<T> bodySubscriber = handler.apply(responseCode, response.headers);
             CompletableFuture<T> cf = receiveData(bodySubscriber, executor);
 
             PushGroup<?> pg = exchange.getPushGroup();
@@ -243,6 +243,7 @@
             return cf;
         } catch (Throwable t) {
             // may be thrown by handler.apply
+            cancelImpl(t);
             return MinimalFuture.failedFuture(t);
         }
     }
@@ -387,6 +388,9 @@
             Log.logHeaders(sb.toString());
         }
 
+        // this will clear the response headers
+        rspHeadersConsumer.reset();
+
         completeResponse(response);
     }
 
@@ -1145,6 +1149,8 @@
                 Log.logHeaders(sb.toString());
             }
 
+            rspHeadersConsumer.reset();
+
             // different implementations for normal streams and pushed streams
             completeResponse(response);
         }
@@ -1184,6 +1190,10 @@
 
     private class HeadersConsumer extends Http2Connection.ValidatingHeadersConsumer {
 
+        void reset() {
+            responseHeaders.clear();
+        }
+
         @Override
         public void onDecoded(CharSequence name, CharSequence value)
                 throws UncheckedIOException
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpHeadersImpl.java	Thu Feb 22 17:33:21 2018 +0000
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpHeadersImpl.java	Fri Feb 23 16:25:32 2018 +0000
@@ -70,4 +70,8 @@
         values.add(value);
         headers.put(name, values);
     }
+
+    public void clear() {
+        headers.clear();
+    }
 }
--- a/test/jdk/java/net/httpclient/AsFileDownloadTest.java	Thu Feb 22 17:33:21 2018 +0000
+++ b/test/jdk/java/net/httpclient/AsFileDownloadTest.java	Fri Feb 23 16:25:32 2018 +0000
@@ -160,6 +160,7 @@
     void test(String uriString, String contentDispositionValue, String expectedFilename)
         throws Exception
     {
+        out.printf("test(%s, %s, %s): starting", uriString, contentDispositionValue, expectedFilename);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
 
         URI uri = URI.create(uriString);
@@ -228,6 +229,7 @@
     void negativeTest(String uriString, String contentDispositionValue)
             throws Exception
     {
+        out.printf("negativeTest(%s, %s): starting", uriString, contentDispositionValue);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
 
         URI uri = URI.create(uriString);
--- a/test/jdk/java/net/httpclient/FlowAdapterSubscriberTest.java	Thu Feb 22 17:33:21 2018 +0000
+++ b/test/jdk/java/net/httpclient/FlowAdapterSubscriberTest.java	Fri Feb 23 16:25:32 2018 +0000
@@ -72,7 +72,7 @@
  * @library /lib/testlibrary http2/server
  * @build Http2TestServer
  * @build jdk.testlibrary.SimpleSSLContext
- * @run testng/othervm FlowAdapterSubscriberTest
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true FlowAdapterSubscriberTest
  */
 
 public class FlowAdapterSubscriberTest {
@@ -86,6 +86,14 @@
     String httpsURI;
     String http2URI;
     String https2URI;
+    static final long start = System.nanoTime();
+    public static String now() {
+        long now = System.nanoTime() - start;
+        long secs = now / 1000_000_000;
+        long mill = (now % 1000_000_000) / 1000_000;
+        long nan = now % 1000_000;
+        return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan);
+    }
 
     @DataProvider(name = "uris")
     public Object[][] variants() {
@@ -101,6 +109,7 @@
 
     @Test
     public void testNull() {
+        System.out.printf(now() + "testNull() starting%n");
         assertThrows(NPE, () -> BodyHandler.fromSubscriber(null));
         assertThrows(NPE, () -> BodyHandler.fromSubscriber(null, Function.identity()));
         assertThrows(NPE, () -> BodyHandler.fromSubscriber(new ListSubscriber(), null));
@@ -121,6 +130,7 @@
 
     @Test(dataProvider = "uris")
     void testListWithFinisher(String url) {
+        System.out.printf(now() + "testListWithFinisher(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("May the luck of the Irish be with you!")).build();
@@ -136,6 +146,7 @@
 
     @Test(dataProvider = "uris")
     void testListWithoutFinisher(String url) {
+        System.out.printf(now() + "testListWithoutFinisher(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("May the luck of the Irish be with you!")).build();
@@ -151,6 +162,7 @@
 
     @Test(dataProvider = "uris")
     void testListWithFinisherBlocking(String url) throws Exception {
+        System.out.printf(now() + "testListWithFinisherBlocking(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("May the luck of the Irish be with you!")).build();
@@ -166,6 +178,7 @@
 
     @Test(dataProvider = "uris")
     void testListWithoutFinisherBlocking(String url) throws Exception {
+        System.out.printf(now() + "testListWithoutFinisherBlocking(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("May the luck of the Irish be with you!")).build();
@@ -183,6 +196,7 @@
 
     @Test(dataProvider = "uris")
     void testCollectionWithFinisher(String url) {
+        System.out.printf(now() + "testCollectionWithFinisher(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("What's the craic?")).build();
@@ -198,6 +212,7 @@
 
     @Test(dataProvider = "uris")
     void testCollectionWithoutFinisher(String url) {
+        System.out.printf(now() + "testCollectionWithoutFinisher(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("What's the craic?")).build();
@@ -213,6 +228,7 @@
 
     @Test(dataProvider = "uris")
     void testCollectionWithFinisherBlocking(String url) throws Exception {
+        System.out.printf(now() + "testCollectionWithFinisherBlocking(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("What's the craic?")).build();
@@ -228,6 +244,7 @@
 
     @Test(dataProvider = "uris")
     void testCollectionWithoutFinisheBlocking(String url) throws Exception {
+        System.out.printf(now() + "testCollectionWithoutFinisheBlocking(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("What's the craic?")).build();
@@ -245,6 +262,7 @@
 
     @Test(dataProvider = "uris")
     void testIterableWithFinisher(String url) {
+        System.out.printf(now() + "testIterableWithFinisher(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("We're sucking diesel now!")).build();
@@ -260,6 +278,7 @@
 
     @Test(dataProvider = "uris")
     void testIterableWithoutFinisher(String url) {
+        System.out.printf(now() + "testIterableWithoutFinisher(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("We're sucking diesel now!")).build();
@@ -275,6 +294,7 @@
 
     @Test(dataProvider = "uris")
     void testIterableWithFinisherBlocking(String url) throws Exception {
+        System.out.printf(now() + "testIterableWithFinisherBlocking(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("We're sucking diesel now!")).build();
@@ -290,6 +310,7 @@
 
     @Test(dataProvider = "uris")
     void testIterableWithoutFinisherBlocking(String url) throws Exception {
+        System.out.printf(now() + "testIterableWithoutFinisherBlocking(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("We're sucking diesel now!")).build();
@@ -307,6 +328,7 @@
 
     @Test(dataProvider = "uris")
     void testObjectWithFinisher(String url) {
+        System.out.printf(now() + "testObjectWithFinisher(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("May the wind always be at your back.")).build();
@@ -322,6 +344,7 @@
 
     @Test(dataProvider = "uris")
     void testObjectWithoutFinisher(String url) {
+        System.out.printf(now() + "testObjectWithoutFinisher(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("May the wind always be at your back.")).build();
@@ -337,6 +360,7 @@
 
     @Test(dataProvider = "uris")
     void testObjectWithFinisherBlocking(String url) throws Exception {
+        System.out.printf(now() + "testObjectWithFinisherBlocking(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("May the wind always be at your back.")).build();
@@ -352,6 +376,7 @@
 
     @Test(dataProvider = "uris")
     void testObjectWithoutFinisherBlocking(String url) throws Exception {
+        System.out.printf(now() + "testObjectWithoutFinisherBlocking(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("May the wind always be at your back.")).build();
@@ -370,6 +395,7 @@
 
     @Test(dataProvider = "uris")
     void mappingFromByteArray(String url) throws Exception {
+        System.out.printf(now() + "mappingFromByteArray(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("We're sucking diesel now!")).build();
@@ -384,6 +410,7 @@
 
     @Test(dataProvider = "uris")
     void mappingFromInputStream(String url) throws Exception {
+        System.out.printf(now() + "mappingFromInputStream(%s) starting%n", url);
         HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
         HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                 .POST(fromString("May the wind always be at your back.")).build();