test/jdk/java/net/httpclient/UnauthorizedTest.java
branchhttp-client-branch
changeset 56643 54e7acad0058
child 56771 73a6534bce94
equal deleted inserted replaced
56639:bd0dba2a0d51 56643:54e7acad0058
       
     1 /*
       
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     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
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  * @test
       
    26  * @bug 8203882
       
    27  * @summary (httpclient) Check that HttpClient throws IOException when
       
    28  *      receiving 401/407 with no WWW-Authenticate/Proxy-Authenticate
       
    29  *      header only in the case where an authenticator is configured
       
    30  *      for the client. If no authenticator is configured the client
       
    31  *      should simply let the caller deal with the unauthorized response.
       
    32  * @modules java.base/sun.net.www.http
       
    33  *          java.net.http/jdk.internal.net.http.common
       
    34  *          java.net.http/jdk.internal.net.http.frame
       
    35  *          java.net.http/jdk.internal.net.http.hpack
       
    36  *          java.logging
       
    37  *          jdk.httpserver
       
    38  * @library /lib/testlibrary /test/lib http2/server
       
    39  * @build Http2TestServer
       
    40  * @build jdk.testlibrary.SimpleSSLContext
       
    41  * @run testng/othervm
       
    42  *       -Djdk.httpclient.HttpClient.log=headers
       
    43  *       UnauthorizedTest
       
    44  */
       
    45 
       
    46 import com.sun.net.httpserver.HttpServer;
       
    47 import com.sun.net.httpserver.HttpsConfigurator;
       
    48 import com.sun.net.httpserver.HttpsServer;
       
    49 import jdk.testlibrary.SimpleSSLContext;
       
    50 import org.testng.annotations.AfterTest;
       
    51 import org.testng.annotations.BeforeTest;
       
    52 import org.testng.annotations.DataProvider;
       
    53 import org.testng.annotations.Test;
       
    54 
       
    55 import javax.net.ssl.SSLContext;
       
    56 import java.io.IOException;
       
    57 import java.io.InputStream;
       
    58 import java.io.OutputStream;
       
    59 import java.net.Authenticator;
       
    60 import java.net.InetAddress;
       
    61 import java.net.InetSocketAddress;
       
    62 import java.net.URI;
       
    63 import java.net.http.HttpClient;
       
    64 import java.net.http.HttpRequest;
       
    65 import java.net.http.HttpResponse;
       
    66 import java.net.http.HttpResponse.BodyHandlers;
       
    67 import java.util.concurrent.ExecutionException;
       
    68 import java.util.concurrent.atomic.AtomicLong;
       
    69 
       
    70 import static java.lang.System.out;
       
    71 import static java.nio.charset.StandardCharsets.UTF_8;
       
    72 import static org.testng.Assert.assertEquals;
       
    73 import static org.testng.Assert.assertTrue;
       
    74 
       
    75 public class UnauthorizedTest implements HttpServerAdapters {
       
    76 
       
    77     SSLContext sslContext;
       
    78     HttpTestServer httpTestServer;        // HTTP/1.1
       
    79     HttpTestServer httpsTestServer;       // HTTPS/1.1
       
    80     HttpTestServer http2TestServer;       // HTTP/2 ( h2c )
       
    81     HttpTestServer https2TestServer;      // HTTP/2 ( h2  )
       
    82     String httpURI;
       
    83     String httpsURI;
       
    84     String http2URI;
       
    85     String https2URI;
       
    86     HttpClient authClient;
       
    87     HttpClient noAuthClient;
       
    88 
       
    89     static final int ITERATIONS = 3;
       
    90 
       
    91     /*
       
    92      * NOT_MODIFIED status code results from a conditional GET where
       
    93      * the server does not (must not) return a response body because
       
    94      * the condition specified in the request disallows it
       
    95      */
       
    96     static final int UNAUTHORIZED = 401;
       
    97     static final int PROXY_UNAUTHORIZED = 407;
       
    98     static final int HTTP_OK = 200;
       
    99     static final String MESSAGE = "Unauthorized";
       
   100 
       
   101     @DataProvider(name = "all")
       
   102     public Object[][] positive() {
       
   103         return new Object[][] {
       
   104                 { httpURI   + "/server", UNAUTHORIZED, true, authClient},
       
   105                 { httpsURI  + "/server", UNAUTHORIZED, true, authClient},
       
   106                 { http2URI  + "/server", UNAUTHORIZED, true, authClient},
       
   107                 { https2URI + "/server", UNAUTHORIZED, true, authClient},
       
   108                 { httpURI   + "/proxy",  PROXY_UNAUTHORIZED, true, authClient},
       
   109                 { httpsURI  + "/proxy",  PROXY_UNAUTHORIZED, true, authClient},
       
   110                 { http2URI  + "/proxy",  PROXY_UNAUTHORIZED, true, authClient},
       
   111                 { https2URI + "/proxy",  PROXY_UNAUTHORIZED, true, authClient},
       
   112                 { httpURI   + "/server", UNAUTHORIZED, false, authClient},
       
   113                 { httpsURI  + "/server", UNAUTHORIZED, false, authClient},
       
   114                 { http2URI  + "/server", UNAUTHORIZED, false, authClient},
       
   115                 { https2URI + "/server", UNAUTHORIZED, false, authClient},
       
   116                 { httpURI   + "/proxy",  PROXY_UNAUTHORIZED, false, authClient},
       
   117                 { httpsURI  + "/proxy",  PROXY_UNAUTHORIZED, false, authClient},
       
   118                 { http2URI  + "/proxy",  PROXY_UNAUTHORIZED, false, authClient},
       
   119                 { https2URI + "/proxy",  PROXY_UNAUTHORIZED, false, authClient},
       
   120                 { httpURI   + "/server", UNAUTHORIZED, true, noAuthClient},
       
   121                 { httpsURI  + "/server", UNAUTHORIZED, true, noAuthClient},
       
   122                 { http2URI  + "/server", UNAUTHORIZED, true, noAuthClient},
       
   123                 { https2URI + "/server", UNAUTHORIZED, true, noAuthClient},
       
   124                 { httpURI   + "/proxy",  PROXY_UNAUTHORIZED, true, noAuthClient},
       
   125                 { httpsURI  + "/proxy",  PROXY_UNAUTHORIZED, true, noAuthClient},
       
   126                 { http2URI  + "/proxy",  PROXY_UNAUTHORIZED, true, noAuthClient},
       
   127                 { https2URI + "/proxy",  PROXY_UNAUTHORIZED, true, noAuthClient},
       
   128                 { httpURI   + "/server", UNAUTHORIZED, false, noAuthClient},
       
   129                 { httpsURI  + "/server", UNAUTHORIZED, false, noAuthClient},
       
   130                 { http2URI  + "/server", UNAUTHORIZED, false, noAuthClient},
       
   131                 { https2URI + "/server", UNAUTHORIZED, false, noAuthClient},
       
   132                 { httpURI   + "/proxy",  PROXY_UNAUTHORIZED, false, noAuthClient},
       
   133                 { httpsURI  + "/proxy",  PROXY_UNAUTHORIZED, false, noAuthClient},
       
   134                 { http2URI  + "/proxy",  PROXY_UNAUTHORIZED, false, noAuthClient},
       
   135                 { https2URI + "/proxy",  PROXY_UNAUTHORIZED, false, noAuthClient},
       
   136         };
       
   137     }
       
   138 
       
   139     static final AtomicLong requestCounter = new AtomicLong();
       
   140 
       
   141     static final Authenticator authenticator = new Authenticator() {
       
   142     };
       
   143 
       
   144     @Test(dataProvider = "all")
       
   145     void test(String uriString, int code, boolean async, HttpClient client) throws Throwable {
       
   146         out.printf("%n---- starting (%s, %d, %s, %s) ----%n",
       
   147                 uriString, code, async ? "async" : "sync",
       
   148                 client.authenticator().isPresent() ? "authClient" : "noAuthClient");
       
   149         URI uri = URI.create(uriString);
       
   150 
       
   151         HttpRequest.Builder requestBuilder = HttpRequest
       
   152                 .newBuilder(uri)
       
   153                 .GET();
       
   154 
       
   155         HttpRequest request = requestBuilder.build();
       
   156         out.println("Initial request: " + request.uri());
       
   157 
       
   158         boolean shouldThrow = client.authenticator().isPresent();
       
   159         String header = (code==UNAUTHORIZED)?"WWW-Authenticate":"Proxy-Authenticate";
       
   160 
       
   161         HttpResponse<String> response = null;
       
   162         try {
       
   163            if (async) {
       
   164                 response = client.send(request, BodyHandlers.ofString());
       
   165             } else {
       
   166                try {
       
   167                    response = client.sendAsync(request, BodyHandlers.ofString()).get();
       
   168                } catch (ExecutionException ex) {
       
   169                    throw ex.getCause();
       
   170                }
       
   171            }
       
   172         } catch (IOException ex) {
       
   173             if (shouldThrow && ex.getMessage().contains(header)) {
       
   174                 System.out.println("Got expected exception: " + ex);
       
   175                 return;
       
   176             } else throw ex;
       
   177         }
       
   178 
       
   179         out.println("  Got response: " + response);
       
   180         assertEquals(response.statusCode(), code);
       
   181         assertEquals(response.body(),
       
   182                 (code == UNAUTHORIZED ? "WWW-" : "Proxy-") + MESSAGE);
       
   183         if (shouldThrow) {
       
   184             throw new RuntimeException("Expected IOException not thrown.");
       
   185         }
       
   186     }
       
   187 
       
   188     // -- Infrastructure
       
   189 
       
   190     @BeforeTest
       
   191     public void setup() throws Exception {
       
   192         sslContext = new SimpleSSLContext().get();
       
   193         if (sslContext == null)
       
   194             throw new AssertionError("Unexpected null sslContext");
       
   195 
       
   196         InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
       
   197 
       
   198         httpTestServer = HttpTestServer.of(HttpServer.create(sa, 0));
       
   199         httpTestServer.addHandler(new UnauthorizedHandler(), "/http1/");
       
   200         httpURI = "http://" + httpTestServer.serverAuthority() + "/http1";
       
   201         HttpsServer httpsServer = HttpsServer.create(sa, 0);
       
   202         httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
       
   203         httpsTestServer = HttpTestServer.of(httpsServer);
       
   204         httpsTestServer.addHandler(new UnauthorizedHandler(),"/https1/");
       
   205         httpsURI = "https://" + httpsTestServer.serverAuthority() + "/https1";
       
   206 
       
   207         http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
       
   208         http2TestServer.addHandler(new UnauthorizedHandler(), "/http2/");
       
   209         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2";
       
   210         https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
       
   211         https2TestServer.addHandler(new UnauthorizedHandler(), "/https2/");
       
   212         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2";
       
   213 
       
   214         authClient = HttpClient.newBuilder()
       
   215                 .proxy(HttpClient.Builder.NO_PROXY)
       
   216                 .sslContext(sslContext)
       
   217                 .authenticator(authenticator)
       
   218                 .build();
       
   219 
       
   220         noAuthClient = HttpClient.newBuilder()
       
   221                 .proxy(HttpClient.Builder.NO_PROXY)
       
   222                 .sslContext(sslContext)
       
   223                 .build();
       
   224 
       
   225         httpTestServer.start();
       
   226         httpsTestServer.start();
       
   227         http2TestServer.start();
       
   228         https2TestServer.start();
       
   229     }
       
   230 
       
   231     @AfterTest
       
   232     public void teardown() throws Exception {
       
   233         httpTestServer.stop();
       
   234         httpsTestServer.stop();
       
   235         http2TestServer.stop();
       
   236         https2TestServer.stop();
       
   237     }
       
   238 
       
   239     static class UnauthorizedHandler implements HttpTestHandler {
       
   240 
       
   241         @Override
       
   242         public void handle(HttpTestExchange t) throws IOException {
       
   243             readAllRequestData(t); // shouldn't be any
       
   244             String method = t.getRequestMethod();
       
   245             String path = t.getRequestURI().getPath();
       
   246             HttpTestResponseHeaders rsph = t.getResponseHeaders();
       
   247 
       
   248             int code;
       
   249             if (path.contains("server")) {
       
   250                 code = UNAUTHORIZED;
       
   251             } else {
       
   252                 code = PROXY_UNAUTHORIZED;
       
   253             }
       
   254             String message = (code == UNAUTHORIZED ? "WWW-" : "Proxy-") + MESSAGE;
       
   255             byte[] bytes = message.getBytes(UTF_8);
       
   256             t.sendResponseHeaders(code, bytes.length);
       
   257             try (OutputStream os = t.getResponseBody()) {
       
   258                 os.write(bytes);
       
   259             }
       
   260         }
       
   261     }
       
   262 
       
   263     static void readAllRequestData(HttpTestExchange t) throws IOException {
       
   264         try (InputStream is = t.getRequestBody()) {
       
   265             is.readAllBytes();
       
   266         }
       
   267     }
       
   268 }