test/jdk/java/net/httpclient/SpecialHeadersTest.java
changeset 53698 68ca8b201925
parent 52554 5f1ca46703f9
equal deleted inserted replaced
53691:dfe9265088b8 53698:68ca8b201925
     1 /*
     1 /*
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    23 
    23 
    24 /*
    24 /*
    25  * @test
    25  * @test
    26  * @summary  Verify that some special headers - such as User-Agent
    26  * @summary  Verify that some special headers - such as User-Agent
    27  *           can be specified by the caller.
    27  *           can be specified by the caller.
    28  * @bug 8203771
    28  * @bug 8203771 8218546
    29  * @modules java.base/sun.net.www.http
    29  * @modules java.base/sun.net.www.http
    30  *          java.net.http/jdk.internal.net.http.common
    30  *          java.net.http/jdk.internal.net.http.common
    31  *          java.net.http/jdk.internal.net.http.frame
    31  *          java.net.http/jdk.internal.net.http.frame
    32  *          java.net.http/jdk.internal.net.http.hpack
    32  *          java.net.http/jdk.internal.net.http.hpack
    33  *          java.logging
    33  *          java.logging
    62 import java.net.http.HttpClient;
    62 import java.net.http.HttpClient;
    63 import java.net.http.HttpHeaders;
    63 import java.net.http.HttpHeaders;
    64 import java.net.http.HttpRequest;
    64 import java.net.http.HttpRequest;
    65 import java.net.http.HttpResponse;
    65 import java.net.http.HttpResponse;
    66 import java.net.http.HttpResponse.BodyHandlers;
    66 import java.net.http.HttpResponse.BodyHandlers;
    67 import java.security.AccessController;
       
    68 import java.security.PrivilegedAction;
       
    69 import java.time.Duration;
    67 import java.time.Duration;
    70 import java.util.ArrayList;
    68 import java.util.ArrayList;
    71 import java.util.Arrays;
    69 import java.util.Arrays;
    72 import java.util.List;
    70 import java.util.List;
    73 import java.util.Locale;
    71 import java.util.Locale;
    74 import java.util.Map;
    72 import java.util.Map;
    75 import java.util.Optional;
    73 import java.util.Optional;
    76 import java.util.function.Function;
    74 import java.util.function.Function;
    77 
       
    78 import static java.lang.System.err;
       
    79 import static java.lang.System.out;
    75 import static java.lang.System.out;
    80 import static java.net.http.HttpClient.Builder.NO_PROXY;
    76 import static java.net.http.HttpClient.Builder.NO_PROXY;
       
    77 import static java.net.http.HttpClient.Version.HTTP_2;
    81 import static java.nio.charset.StandardCharsets.US_ASCII;
    78 import static java.nio.charset.StandardCharsets.US_ASCII;
    82 import org.testng.Assert;
    79 import org.testng.Assert;
    83 import static org.testng.Assert.assertEquals;
    80 import static org.testng.Assert.assertEquals;
       
    81 import static org.testng.Assert.assertTrue;
    84 
    82 
    85 public class SpecialHeadersTest implements HttpServerAdapters {
    83 public class SpecialHeadersTest implements HttpServerAdapters {
    86 
    84 
    87     SSLContext sslContext;
    85     SSLContext sslContext;
    88     HttpTestServer httpTestServer;         // HTTP/1.1    [ 4 servers ]
    86     HttpTestServer httpTestServer;         // HTTP/1.1    [ 4 servers ]
   149 
   147 
   150     static final Map<String, Function<URI,String>> DEFAULTS = Map.of(
   148     static final Map<String, Function<URI,String>> DEFAULTS = Map.of(
   151         "USER-AGENT", u -> userAgent(), "HOST", u -> u.getRawAuthority());
   149         "USER-AGENT", u -> userAgent(), "HOST", u -> u.getRawAuthority());
   152 
   150 
   153     @Test(dataProvider = "variants")
   151     @Test(dataProvider = "variants")
   154     void test(String uriString, String headerNameAndValue, boolean sameClient) throws Exception {
   152     void test(String uriString,
       
   153               String headerNameAndValue,
       
   154               boolean sameClient)
       
   155         throws Exception
       
   156     {
   155         out.println("\n--- Starting ");
   157         out.println("\n--- Starting ");
   156 
   158 
   157         int index = headerNameAndValue.indexOf(":");
   159         int index = headerNameAndValue.indexOf(":");
   158         String name = headerNameAndValue.substring(0, index);
   160         String name = headerNameAndValue.substring(0, index);
   159         String v = headerNameAndValue.substring(index+1).trim();
   161         String v = headerNameAndValue.substring(index+1).trim();
   181             out.println("Got response: " + resp);
   183             out.println("Got response: " + resp);
   182             out.println("Got body: " + resp.body());
   184             out.println("Got body: " + resp.body());
   183             assertEquals(resp.statusCode(), 200,
   185             assertEquals(resp.statusCode(), 200,
   184                     "Expected 200, got:" + resp.statusCode());
   186                     "Expected 200, got:" + resp.statusCode());
   185 
   187 
   186             String receivedHeaderString = value == null ? null
   188             boolean isInitialRequest = i == 0;
   187                     : resp.headers().firstValue("X-"+key).get();
   189             boolean isSecure = uri.getScheme().equalsIgnoreCase("https");
   188             out.println("Got X-" + key + ": " + resp.headers().allValues("X-"+key));
   190             boolean isHTTP2 = resp.version() == HTTP_2;
   189             if (value != null) {
   191             boolean isNotH2CUpgrade = isSecure || (sameClient == true && !isInitialRequest);
   190                 assertEquals(receivedHeaderString, value);
   192             boolean isDefaultHostHeader = name.equalsIgnoreCase("host") && useDefault;
   191                 assertEquals(resp.headers().allValues("X-"+key), List.of(value));
   193 
       
   194             // By default, HTTP/2 sets the `:authority:` pseudo-header, instead
       
   195             // of the `Host` header. Therefore, there should be no "X-Host"
       
   196             // header in the response, except the response to the h2c Upgrade
       
   197             // request which will have been sent through HTTP/1.1.
       
   198 
       
   199             if (isDefaultHostHeader && isHTTP2 && isNotH2CUpgrade) {
       
   200                 assertTrue(resp.headers().firstValue("X-" + key).isEmpty());
       
   201                 assertTrue(resp.headers().allValues("X-" + key).isEmpty());
       
   202                 out.println("No X-" + key + " header received, as expected");
   192             } else {
   203             } else {
   193                 assertEquals(resp.headers().allValues("X-"+key).size(), 0);
   204                 String receivedHeaderString = value == null ? null
   194             }
   205                         : resp.headers().firstValue("X-"+key).get();
   195 
   206                 out.println("Got X-" + key + ": " + resp.headers().allValues("X-"+key));
       
   207                 if (value != null) {
       
   208                     assertEquals(receivedHeaderString, value);
       
   209                     assertEquals(resp.headers().allValues("X-"+key), List.of(value));
       
   210                 } else {
       
   211                     assertEquals(resp.headers().allValues("X-"+key).size(), 0);
       
   212                 }
       
   213             }
   196         }
   214         }
   197     }
   215     }
   198 
   216 
   199     @Test(dataProvider = "variants")
   217     @Test(dataProvider = "variants")
   200     void testHomeMadeIllegalHeader(String uriString, String headerNameAndValue, boolean sameClient) throws Exception {
   218     void testHomeMadeIllegalHeader(String uriString,
       
   219                                    String headerNameAndValue,
       
   220                                    boolean sameClient)
       
   221         throws Exception
       
   222     {
   201         out.println("\n--- Starting ");
   223         out.println("\n--- Starting ");
   202         final URI uri = URI.create(uriString);
   224         final URI uri = URI.create(uriString);
   203 
   225 
   204         HttpClient client = HttpClient.newBuilder()
   226         HttpClient client = HttpClient.newBuilder()
   205                 .proxy(NO_PROXY)
   227                 .proxy(NO_PROXY)
   264             if (!useDefault) {
   286             if (!useDefault) {
   265                 requestBuilder.header(name, value);
   287                 requestBuilder.header(name, value);
   266             }
   288             }
   267             HttpRequest request = requestBuilder.build();
   289             HttpRequest request = requestBuilder.build();
   268 
   290 
       
   291             boolean isInitialRequest = i == 0;
       
   292             boolean isSecure = uri.getScheme().equalsIgnoreCase("https");
       
   293             boolean isNotH2CUpgrade = isSecure || (sameClient == true && !isInitialRequest);
       
   294             boolean isDefaultHostHeader = name.equalsIgnoreCase("host") && useDefault;
       
   295 
   269             client.sendAsync(request, BodyHandlers.ofString())
   296             client.sendAsync(request, BodyHandlers.ofString())
   270                     .thenApply(response -> {
   297                     .thenApply(response -> {
   271                         out.println("Got response: " + response);
   298                         out.println("Got response: " + response);
   272                         out.println("Got body: " + response.body());
   299                         out.println("Got body: " + response.body());
   273                         assertEquals(response.statusCode(), 200);
   300                         assertEquals(response.statusCode(), 200);
   274                         return response;})
   301                         return response;})
   275                     .thenAccept(resp -> {
   302                     .thenAccept(resp -> {
   276                         String receivedHeaderString = value == null ? null
   303                         // By default, HTTP/2 sets the `:authority:` pseudo-header, instead
   277                                 : resp.headers().firstValue("X-"+key).get();
   304                         // of the `Host` header. Therefore, there should be no "X-Host"
   278                         out.println("Got X-" + key + ": " + resp.headers().allValues("X-"+key));
   305                         // header in the response, except the response to the h2c Upgrade
   279                         if (value != null) {
   306                         // request which will have been sent through HTTP/1.1.
   280                             assertEquals(receivedHeaderString, value);
   307 
   281                             assertEquals(resp.headers().allValues("X-" + key), List.of(value));
   308                         if (isDefaultHostHeader && resp.version() == HTTP_2 && isNotH2CUpgrade) {
       
   309                             assertTrue(resp.headers().firstValue("X-" + key).isEmpty());
       
   310                             assertTrue(resp.headers().allValues("X-" + key).isEmpty());
       
   311                             out.println("No X-" + key + " header received, as expected");
   282                         } else {
   312                         } else {
   283                             assertEquals(resp.headers().allValues("X-" + key).size(), 1);
   313                             String receivedHeaderString = value == null ? null
   284                         } })
   314                                     : resp.headers().firstValue("X-"+key).get();
       
   315                             out.println("Got X-" + key + ": " + resp.headers().allValues("X-"+key));
       
   316                             if (value != null) {
       
   317                                 assertEquals(receivedHeaderString, value);
       
   318                                 assertEquals(resp.headers().allValues("X-" + key), List.of(value));
       
   319                             } else {
       
   320                                 assertEquals(resp.headers().allValues("X-" + key).size(), 1);
       
   321                             }
       
   322                         }
       
   323                     })
   285                     .join();
   324                     .join();
   286         }
   325         }
   287     }
   326     }
   288 
   327 
   289     static String serverAuthority(HttpTestServer server) {
   328     static String serverAuthority(HttpTestServer server) {