--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/www/protocol/http/B5017051.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 5017051 6360774
+ * @run main/othervm B5017051
+ * @summary Tests CR 5017051 & 6360774
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import com.sun.net.httpserver.*;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+
+/*
+ * Part 1:
+ * First request sent to the http server will not have an "Authorization" header set and
+ * the server will respond with a 401, but not until it has set a cookie in the response
+ * headers. The subsequent request ( comes from HttpURLConnection's authentication retry )
+ * will have the appropriate Authorization header and the servers context handler will be
+ * invoked. The test passes only if the client (HttpURLConnection) has sent the cookie
+ * in its second request that had been set via the first response from the server.
+ *
+ * Part 2:
+ * Preload the CookieManager with a cookie. Make a http request that requires authentication
+ * The cookie will be sent in the first request (without the Authorization header), the
+ * server will respond with a 401 (from MyBasicAuthFilter) and the client will add the
+ * appropriate Authorization header. This tests ensures that there is only one Cookie header
+ * in the request that actually makes it to the Http servers context handler.
+ */
+
+public class B5017051
+{
+ com.sun.net.httpserver.HttpServer httpServer;
+ ExecutorService executorService;
+
+ public static void main(String[] args)
+ {
+ new B5017051();
+ }
+
+ public B5017051()
+ {
+ try {
+ startHttpServer();
+ doClient();
+ } catch (IOException ioe) {
+ System.err.println(ioe);
+ }
+ }
+
+ void doClient() {
+ java.net.Authenticator.setDefault(new MyAuthenticator());
+ CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
+
+ try {
+ InetSocketAddress address = httpServer.getAddress();
+
+ // Part 1
+ URL url = new URL("http://" + address.getHostName() + ":" + address.getPort() + "/test/");
+ HttpURLConnection uc = (HttpURLConnection)url.openConnection();
+ int resp = uc.getResponseCode();
+ if (resp != 200)
+ throw new RuntimeException("Failed: Part 1, Response code is not 200");
+
+ System.out.println("Response code from Part 1 = 200 OK");
+
+ // Part 2
+ URL url2 = new URL("http://" + address.getHostName() + ":" + address.getPort() + "/test2/");
+
+ // can use the global CookieHandler used for the first test as the URL's are different
+ CookieHandler ch = CookieHandler.getDefault();
+ Map<String,List<String>> header = new HashMap<String,List<String>>();
+ List<String> values = new LinkedList<String>();
+ values.add("Test2Cookie=\"TEST2\"; path=\"/test2/\"");
+ header.put("Set-Cookie2", values);
+
+ // preload the CookieHandler with a cookie for our URL
+ // so that it will be sent during the first request
+ ch.put(url2.toURI(), header);
+
+ uc = (HttpURLConnection)url2.openConnection();
+ resp = uc.getResponseCode();
+ if (resp != 200)
+ throw new RuntimeException("Failed: Part 2, Response code is not 200");
+
+ System.out.println("Response code from Part 2 = 200 OK");
+
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (URISyntaxException ue) {
+ ue.printStackTrace();
+ } finally {
+ httpServer.stop(1);
+ executorService.shutdown();
+ }
+ }
+
+ /**
+ * Http Server
+ */
+ public void startHttpServer() throws IOException {
+ httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0);
+
+ // create HttpServer context for Part 1.
+ HttpContext ctx = httpServer.createContext("/test/", new MyHandler());
+ ctx.setAuthenticator( new MyBasicAuthenticator("foo"));
+ // CookieFilter needs to be executed before Authenticator.
+ ctx.getFilters().add(0, new CookieFilter());
+
+ // create HttpServer context for Part 2.
+ HttpContext ctx2 = httpServer.createContext("/test2/", new MyHandler2());
+ ctx2.setAuthenticator( new MyBasicAuthenticator("foobar"));
+
+ executorService = Executors.newCachedThreadPool();
+ httpServer.setExecutor(executorService);
+ httpServer.start();
+ }
+
+ class MyHandler implements HttpHandler {
+ public void handle(HttpExchange t) throws IOException {
+ InputStream is = t.getRequestBody();
+ Headers reqHeaders = t.getRequestHeaders();
+ Headers resHeaders = t.getResponseHeaders();
+ while (is.read () != -1) ;
+ is.close();
+
+ if (!reqHeaders.containsKey("Authorization"))
+ t.sendResponseHeaders(400, -1);
+
+ List<String> cookies = reqHeaders.get("Cookie");
+ if (cookies != null) {
+ for (String str : cookies) {
+ if (str.equals("Customer=WILE_E_COYOTE"))
+ t.sendResponseHeaders(200, -1);
+ }
+ }
+ t.sendResponseHeaders(400, -1);
+ }
+ }
+
+ class MyHandler2 implements HttpHandler {
+ public void handle(HttpExchange t) throws IOException {
+ InputStream is = t.getRequestBody();
+ Headers reqHeaders = t.getRequestHeaders();
+ Headers resHeaders = t.getResponseHeaders();
+ while (is.read () != -1) ;
+ is.close();
+
+ if (!reqHeaders.containsKey("Authorization"))
+ t.sendResponseHeaders(400, -1);
+
+ List<String> cookies = reqHeaders.get("Cookie");
+
+ // there should only be one Cookie header
+ if (cookies != null && (cookies.size() == 1)) {
+ t.sendResponseHeaders(200, -1);
+ }
+ t.sendResponseHeaders(400, -1);
+ }
+ }
+
+ class MyAuthenticator extends java.net.Authenticator {
+ public PasswordAuthentication getPasswordAuthentication () {
+ return new PasswordAuthentication("tester", "passwd".toCharArray());
+ }
+ }
+
+ class MyBasicAuthenticator extends BasicAuthenticator
+ {
+ public MyBasicAuthenticator(String realm) {
+ super(realm);
+ }
+
+ public boolean checkCredentials (String username, String password) {
+ return username.equals("tester") && password.equals("passwd");
+ }
+ }
+
+ class CookieFilter extends Filter
+ {
+ public void doFilter(HttpExchange t, Chain chain) throws IOException
+ {
+ Headers resHeaders = t.getResponseHeaders();
+ Headers reqHeaders = t.getRequestHeaders();
+
+ if (!reqHeaders.containsKey("Authorization"))
+ resHeaders.set("Set-Cookie2", "Customer=\"WILE_E_COYOTE\"; path=\"/test/\"");
+
+ chain.doFilter(t);
+ }
+
+ public void destroy(HttpContext c) { }
+
+ public void init(HttpContext c) { }
+
+ public String description() {
+ return new String("Filter for setting a cookie for requests without an \"Authorization\" header.");
+ }
+ }
+}