test/jdk/java/net/httpclient/DigestEchoClient.java
branchhttp-client-branch
changeset 56054 352e845ae744
parent 56041 b4b5e09ef3cc
child 56070 66a9c3185028
equal deleted inserted replaced
56053:8588095e95b0 56054:352e845ae744
    48 import jdk.incubator.http.HttpClient;
    48 import jdk.incubator.http.HttpClient;
    49 import jdk.incubator.http.HttpClient.Version;
    49 import jdk.incubator.http.HttpClient.Version;
    50 import jdk.incubator.http.HttpRequest;
    50 import jdk.incubator.http.HttpRequest;
    51 import jdk.incubator.http.HttpResponse;
    51 import jdk.incubator.http.HttpResponse;
    52 import jdk.testlibrary.SimpleSSLContext;
    52 import jdk.testlibrary.SimpleSSLContext;
       
    53 import sun.net.NetProperties;
    53 import sun.net.www.HeaderParser;
    54 import sun.net.www.HeaderParser;
    54 import static java.lang.System.out;
    55 import static java.lang.System.out;
    55 import static java.lang.String.format;
    56 import static java.lang.String.format;
    56 import static jdk.incubator.http.HttpResponse.BodyHandler.asLines;
    57 import static jdk.incubator.http.HttpResponse.BodyHandler.asLines;
    57 
    58 
    62  * @bug 8087112
    63  * @bug 8087112
    63  * @library /lib/testlibrary
    64  * @library /lib/testlibrary
    64  * @build jdk.testlibrary.SimpleSSLContext DigestEchoServer DigestEchoClient
    65  * @build jdk.testlibrary.SimpleSSLContext DigestEchoServer DigestEchoClient
    65  * @modules jdk.incubator.httpclient
    66  * @modules jdk.incubator.httpclient
    66  *          java.base/sun.net.www
    67  *          java.base/sun.net.www
       
    68  *          java.base/sun.net
    67  * @run main/othervm DigestEchoClient
    69  * @run main/othervm DigestEchoClient
       
    70  * @run main/othervm -Djdk.http.auth.proxying.disabledSchemes=
       
    71  *                   -Djdk.http.auth.tunneling.disabledSchemes=
       
    72  *                   DigestEchoClient
    68  */
    73  */
    69 
    74 
    70 public class DigestEchoClient {
    75 public class DigestEchoClient {
    71 
    76 
    72     static final String data[] = {
    77     static final String data[] = {
   134             }
   139             }
   135         }
   140         }
   136 
   141 
   137         private static final ConcurrentMap<String, EchoServers> servers = new ConcurrentHashMap<>();
   142         private static final ConcurrentMap<String, EchoServers> servers = new ConcurrentHashMap<>();
   138     }
   143     }
       
   144 
       
   145     final static String PROXY_DISABLED = NetProperties.get("jdk.http.auth.proxying.disabledSchemes");
       
   146     final static String TUNNEL_DISABLED = NetProperties.get("jdk.http.auth.tunneling.disabledSchemes");
       
   147     static {
       
   148         System.out.println("jdk.http.auth.proxying.disabledSchemes=" + PROXY_DISABLED);
       
   149         System.out.println("jdk.http.auth.tunneling.disabledSchemes=" + TUNNEL_DISABLED);
       
   150     }
       
   151 
   139 
   152 
   140 
   153 
   141     static final AtomicInteger NC = new AtomicInteger();
   154     static final AtomicInteger NC = new AtomicInteger();
   142     static final Random random = new Random();
   155     static final Random random = new Random();
   143     static final SSLContext context;
   156     static final SSLContext context;
   264                     digestCount.get(), digests.get()));
   277                     digestCount.get(), digests.get()));
   265             System.out.println(" ---------------------------------------------------------- ");
   278             System.out.println(" ---------------------------------------------------------- ");
   266         }
   279         }
   267     }
   280     }
   268 
   281 
       
   282     boolean isSchemeDisabled() {
       
   283         String disabledSchemes;
       
   284         if (isProxy(authType)) {
       
   285             disabledSchemes = useSSL
       
   286                     ? TUNNEL_DISABLED
       
   287                     : PROXY_DISABLED;
       
   288         } else return false;
       
   289         if (disabledSchemes == null
       
   290                 || disabledSchemes.isEmpty()) {
       
   291             return false;
       
   292         }
       
   293         String scheme;
       
   294         switch (authScheme) {
       
   295             case DIGEST:
       
   296                 scheme = "Digest";
       
   297                 break;
       
   298             case BASIC:
       
   299                 scheme = "Basic";
       
   300                 break;
       
   301             case BASICSERVER:
       
   302                 scheme = "Basic";
       
   303                 break;
       
   304             case NONE:
       
   305                 return false;
       
   306             default:
       
   307                 throw new InternalError("Unknown auth scheme: " + authScheme);
       
   308         }
       
   309         return Stream.of(disabledSchemes.split(","))
       
   310                 .map(String::trim)
       
   311                 .filter(scheme::equalsIgnoreCase)
       
   312                 .findAny()
       
   313                 .isPresent();
       
   314     }
       
   315 
   269     final static AtomicLong basics = new AtomicLong();
   316     final static AtomicLong basics = new AtomicLong();
   270     final static AtomicLong basicCount = new AtomicLong();
   317     final static AtomicLong basicCount = new AtomicLong();
   271     // @Test
   318     // @Test
   272     void testBasic(HttpClient.Version version, boolean async,
   319     void testBasic(HttpClient.Version version, boolean async,
   273                    boolean expectContinue, boolean preemptive)
   320                    boolean expectContinue, boolean preemptive)
   303                 if (addHeaders) {
   350                 if (addHeaders) {
   304                     // handle authentication ourselves
   351                     // handle authentication ourselves
   305                     assert !client.authenticator().isPresent();
   352                     assert !client.authenticator().isPresent();
   306                     if (auth == null) auth = "Basic " + getBasicAuth("arthur");
   353                     if (auth == null) auth = "Basic " + getBasicAuth("arthur");
   307                     try {
   354                     try {
   308                         if ((i > 0 || preemptive) && (!isTunnel || i == 0)) {
   355                         if ((i > 0 || preemptive)
       
   356                                 && (!isTunnel || i == 0 || isSchemeDisabled())) {
   309                             // In case of a SSL tunnel through proxy then only the
   357                             // In case of a SSL tunnel through proxy then only the
   310                             // first request should require proxy authorization
   358                             // first request should require proxy authorization
   311                             // Though this might be invalidated if the server decides
   359                             // Though this might be invalidated if the server decides
   312                             // to close the connection...
   360                             // to close the connection...
   313                             out.println(String.format("%s adding %s: %s",
   361                             out.println(String.format("%s adding %s: %s",
   344                         t = t.getCause();
   392                         t = t.getCause();
   345                     }
   393                     }
   346                     throw new RuntimeException("Unexpected exception: " + t, t);
   394                     throw new RuntimeException("Unexpected exception: " + t, t);
   347                 }
   395                 }
   348 
   396 
   349                 if (addHeaders && !preemptive && i==0) {
   397                 if (addHeaders && !preemptive && (i==0 || isSchemeDisabled())) {
   350                     assert resp.statusCode() == 401 || resp.statusCode() == 407;
   398                     assert resp.statusCode() == 401 || resp.statusCode() == 407;
   351                     request = HttpRequest.newBuilder(uri).version(version)
   399                     request = HttpRequest.newBuilder(uri).version(version)
   352                             .POST(reqBody).header(authorizationKey(authType), auth).build();
   400                             .POST(reqBody).header(authorizationKey(authType), auth).build();
   353                     if (async) {
   401                     if (async) {
   354                         resp = client.sendAsync(request, asLines()).join();
   402                         resp = client.sendAsync(request, asLines()).join();
   355                     } else {
   403                     } else {
   356                         resp = client.send(request, asLines());
   404                         resp = client.send(request, asLines());
   357                     }
   405                     }
   358                 }
   406                 }
   359                 assert resp.statusCode() == 200;
   407                 final List<String> respLines;
   360                 List<String> respLines = resp.body().collect(Collectors.toList());
   408                 try {
   361                 long stop = System.nanoTime();
   409                     if (isSchemeDisabled()) {
   362                 synchronized (basicCount) {
   410                         if (resp.statusCode() != 407) {
   363                     long n = basicCount.getAndIncrement();
   411                             throw new RuntimeException("expected 407 not received");
   364                     basics.set((basics.get() * n + (stop - start)) / (n + 1));
   412                         }
       
   413                         System.out.println("Scheme disabled for [" + authType
       
   414                                 + ", " + authScheme
       
   415                                 + ", " + (useSSL ? "HTTP" : "HTTPS")
       
   416                                 + "]: Received expected " + resp.statusCode());
       
   417                         continue;
       
   418                     } else {
       
   419                         System.out.println("Scheme enabled for [" + authType
       
   420                                 + ", " + authScheme
       
   421                                 + ", " + (useSSL ? "HTTPS" : "HTTP")
       
   422                                 + "]: Expecting 200");
       
   423                         assert resp.statusCode() == 200;
       
   424                         respLines = resp.body().collect(Collectors.toList());
       
   425                     }
       
   426                 } finally {
       
   427                     long stop = System.nanoTime();
       
   428                     synchronized (basicCount) {
       
   429                         long n = basicCount.getAndIncrement();
       
   430                         basics.set((basics.get() * n + (stop - start)) / (n + 1));
       
   431                     }
   365                 }
   432                 }
   366                 if (!lines.equals(respLines)) {
   433                 if (!lines.equals(respLines)) {
   367                     throw new RuntimeException("Unexpected response: " + respLines);
   434                     throw new RuntimeException("Unexpected response: " + respLines);
   368                 }
   435                 }
   369             }
   436             }
   416                 String digestMethod = isTunnel ? "CONNECT" : "POST";
   483                 String digestMethod = isTunnel ? "CONNECT" : "POST";
   417 
   484 
   418                 // In case of a tunnel connection only the first request
   485                 // In case of a tunnel connection only the first request
   419                 // which establishes the tunnel needs to authenticate with
   486                 // which establishes the tunnel needs to authenticate with
   420                 // the proxy.
   487                 // the proxy.
   421                 if (challenge != null && !isTunnel) {
   488                 if (challenge != null && (!isTunnel || isSchemeDisabled())) {
   422                     assert cnonceStr != null;
   489                     assert cnonceStr != null;
   423                     String auth = digestResponse(uri, digestMethod, challenge, cnonceStr);
   490                     String auth = digestResponse(uri, digestMethod, challenge, cnonceStr);
   424                     try {
   491                     try {
   425                         reqBuilder = reqBuilder.header(authorizationKey(authType), auth);
   492                         reqBuilder = reqBuilder.header(authorizationKey(authType), auth);
   426                     } catch (IllegalArgumentException x) {
   493                     } catch (IllegalArgumentException x) {
   440                 assert challenge != null || resp.statusCode() == 401 || resp.statusCode() == 407;
   507                 assert challenge != null || resp.statusCode() == 401 || resp.statusCode() == 407;
   441                 if (resp.statusCode() == 401 || resp.statusCode() == 407) {
   508                 if (resp.statusCode() == 401 || resp.statusCode() == 407) {
   442                     // This assert may need to be relaxed if our server happened to
   509                     // This assert may need to be relaxed if our server happened to
   443                     // decide to close the tunnel connection, in which case we would
   510                     // decide to close the tunnel connection, in which case we would
   444                     // receive 407 again...
   511                     // receive 407 again...
   445                     assert challenge == null || !isTunnel
   512                     assert challenge == null || !isTunnel || isSchemeDisabled()
   446                             : "No proxy auth should be required after establishing an SSL tunnel";
   513                             : "No proxy auth should be required after establishing an SSL tunnel";
   447 
   514 
   448                     System.out.println("Received " + resp.statusCode() + " answering challenge...");
   515                     System.out.println("Received " + resp.statusCode() + " answering challenge...");
   449                     random.nextBytes(cnonce);
   516                     random.nextBytes(cnonce);
   450                     cnonceStr = new BigInteger(1, cnonce).toString(16);
   517                     cnonceStr = new BigInteger(1, cnonce).toString(16);
   474                     } else {
   541                     } else {
   475                         resp = client.send(request, asLines());
   542                         resp = client.send(request, asLines());
   476                     }
   543                     }
   477                     System.out.println(resp);
   544                     System.out.println(resp);
   478                 }
   545                 }
   479                 assert resp.statusCode() == 200;
   546                 final List<String> respLines;
   480                 List<String> respLines = resp.body().collect(Collectors.toList());
   547                 try {
   481                 long stop = System.nanoTime();
   548                     if (isSchemeDisabled()) {
   482                 synchronized (digestCount) {
   549                         if (resp.statusCode() != 407) {
   483                     long n = digestCount.getAndIncrement();
   550                             throw new RuntimeException("expected 407 not received");
   484                     digests.set((digests.get() * n + (stop - start)) / (n + 1));
   551                         }
       
   552                         System.out.println("Scheme disabled for [" + authType
       
   553                                 + ", " + authScheme +
       
   554                                 ", " + (useSSL ? "HTTP" : "HTTPS")
       
   555                                 + "]: Received expected " + resp.statusCode());
       
   556                         continue;
       
   557                     } else {
       
   558                         assert resp.statusCode() == 200;
       
   559                         respLines = resp.body().collect(Collectors.toList());
       
   560                     }
       
   561                 } finally {
       
   562                     long stop = System.nanoTime();
       
   563                     synchronized (basicCount) {
       
   564                         long n = basicCount.getAndIncrement();
       
   565                         basics.set((basics.get() * n + (stop - start)) / (n + 1));
       
   566                     }
   485                 }
   567                 }
   486                 if (!lines.equals(respLines)) {
   568                 if (!lines.equals(respLines)) {
   487                     throw new RuntimeException("Unexpected response: " + respLines);
   569                     throw new RuntimeException("Unexpected response: " + respLines);
   488                 }
   570                 }
   489             }
   571             }