1 /* 2 * Copyright (c) 2015, 2017, 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 * library /lib/testlibrary/ / 26 * build jdk.testlibrary.SimpleSSLContext ProxyServer 27 * compile ../../../com/sun/net/httpserver/LogFilter.java 28 * compile ../../../com/sun/net/httpserver/EchoHandler.java 29 * compile ../../../com/sun/net/httpserver/FileServerHandler.java 30 */ 31 import com.sun.net.httpserver.Headers; 32 import com.sun.net.httpserver.HttpContext; 33 import com.sun.net.httpserver.HttpExchange; 34 import com.sun.net.httpserver.HttpHandler; 35 import com.sun.net.httpserver.HttpServer; 36 import com.sun.net.httpserver.HttpsConfigurator; 37 import com.sun.net.httpserver.HttpsServer; 38 import java.io.IOException; 39 import java.io.InputStream; 40 import java.io.OutputStream; 41 import java.net.InetSocketAddress; 42 import java.nio.file.Path; 43 import java.util.HashSet; 44 import java.util.concurrent.BrokenBarrierException; 45 import java.util.concurrent.CyclicBarrier; 46 import java.util.concurrent.ExecutorService; 47 import java.util.concurrent.Executors; 48 import java.util.logging.ConsoleHandler; 49 import java.util.logging.Level; 50 import java.util.logging.Logger; 51 import javax.net.ssl.SSLContext; 52 import jdk.testlibrary.SimpleSSLContext; 53 54 public class LightWeightHttpServer { 55 56 static SSLContext ctx; 57 static HttpServer httpServer; 58 static HttpsServer httpsServer; 59 static ExecutorService executor; 60 static int port; 61 static int httpsport; 62 static String httproot; 63 static String httpsroot; 64 static ProxyServer proxy; 65 static int proxyPort; 66 static RedirectErrorHandler redirectErrorHandler, redirectErrorHandlerSecure; 67 static RedirectHandler redirectHandler, redirectHandlerSecure; 68 static DelayHandler delayHandler; 69 static final String midSizedFilename = "/files/notsobigfile.txt"; 70 static final String smallFilename = "/files/smallfile.txt"; 71 static Path midSizedFile; 72 static Path smallFile; 73 static String fileroot; 74 75 public static void initServer() throws IOException { 76 77 Logger logger = Logger.getLogger("com.sun.net.httpserver"); 78 ConsoleHandler ch = new ConsoleHandler(); 79 logger.setLevel(Level.ALL); 80 ch.setLevel(Level.ALL); 81 logger.addHandler(ch); 82 83 String root = System.getProperty("test.src") + "/docs"; 84 InetSocketAddress addr = new InetSocketAddress(0); 85 httpServer = HttpServer.create(addr, 0); 86 if (httpServer instanceof HttpsServer) { 87 throw new RuntimeException("should not be httpsserver"); 88 } 89 httpsServer = HttpsServer.create(addr, 0); 90 HttpHandler h = new FileServerHandler(root); 91 92 HttpContext c1 = httpServer.createContext("/files", h); 93 HttpContext c2 = httpsServer.createContext("/files", h); 94 HttpContext c3 = httpServer.createContext("/echo", new EchoHandler()); 95 redirectHandler = new RedirectHandler("/redirect"); 96 redirectHandlerSecure = new RedirectHandler("/redirect"); 97 HttpContext c4 = httpServer.createContext("/redirect", redirectHandler); 98 HttpContext c41 = httpsServer.createContext("/redirect", redirectHandlerSecure); 99 HttpContext c5 = httpsServer.createContext("/echo", new EchoHandler()); 100 HttpContext c6 = httpServer.createContext("/keepalive", new KeepAliveHandler()); 101 redirectErrorHandler = new RedirectErrorHandler("/redirecterror"); 102 redirectErrorHandlerSecure = new RedirectErrorHandler("/redirecterror"); 103 HttpContext c7 = httpServer.createContext("/redirecterror", redirectErrorHandler); 104 HttpContext c71 = httpsServer.createContext("/redirecterror", redirectErrorHandlerSecure); 105 delayHandler = new DelayHandler(); 106 HttpContext c8 = httpServer.createContext("/delay", delayHandler); 107 HttpContext c81 = httpsServer.createContext("/delay", delayHandler); 108 109 executor = Executors.newCachedThreadPool(); 110 httpServer.setExecutor(executor); 111 httpsServer.setExecutor(executor); 112 ctx = new SimpleSSLContext().get(); 113 httpsServer.setHttpsConfigurator(new HttpsConfigurator(ctx)); 114 httpServer.start(); 115 httpsServer.start(); 116 117 port = httpServer.getAddress().getPort(); 118 System.out.println("HTTP server port = " + port); 119 httpsport = httpsServer.getAddress().getPort(); 120 System.out.println("HTTPS server port = " + httpsport); 121 httproot = "http://127.0.0.1:" + port + "/"; 122 httpsroot = "https://127.0.0.1:" + httpsport + "/"; 123 124 proxy = new ProxyServer(0, false); 125 proxyPort = proxy.getPort(); 126 System.out.println("Proxy port = " + proxyPort); 127 } 128 129 public static void stop() throws IOException { 130 if (httpServer != null) { 131 httpServer.stop(0); 132 } 133 if (httpsServer != null) { 134 httpsServer.stop(0); 135 } 136 if (proxy != null) { 137 proxy.close(); 138 } 139 if (executor != null) { 140 executor.shutdownNow(); 141 } 142 } 143 144 static class RedirectErrorHandler implements HttpHandler { 145 146 String root; 147 volatile int count = 1; 148 149 RedirectErrorHandler(String root) { 150 this.root = root; 151 } 152 153 synchronized int count() { 154 return count; 155 } 156 157 synchronized void increment() { 158 count++; 159 } 160 161 @Override 162 public synchronized void handle(HttpExchange t) 163 throws IOException { 164 byte[] buf = new byte[2048]; 165 try (InputStream is = t.getRequestBody()) { 166 while (is.read(buf) != -1) ; 167 } 168 169 Headers map = t.getResponseHeaders(); 170 String redirect = root + "/foo/" + Integer.toString(count); 171 increment(); 172 map.add("Location", redirect); 173 t.sendResponseHeaders(301, -1); 174 t.close(); 175 } 176 } 177 178 static class RedirectHandler implements HttpHandler { 179 180 String root; 181 volatile int count = 0; 182 183 RedirectHandler(String root) { 184 this.root = root; 185 } 186 187 @Override 188 public synchronized void handle(HttpExchange t) 189 throws IOException { 190 byte[] buf = new byte[2048]; 191 try (InputStream is = t.getRequestBody()) { 192 while (is.read(buf) != -1) ; 193 } 194 195 Headers map = t.getResponseHeaders(); 196 197 if (count++ < 1) { 198 map.add("Location", root + "/foo/" + count); 199 } else { 200 map.add("Location", SmokeTest.midSizedFilename); 201 } 202 t.sendResponseHeaders(301, -1); 203 t.close(); 204 } 205 206 int count() { 207 return count; 208 } 209 210 void reset() { 211 count = 0; 212 } 213 } 214 215 static class KeepAliveHandler implements HttpHandler { 216 217 volatile int counter = 0; 218 HashSet<Integer> portSet = new HashSet<>(); 219 volatile int[] ports = new int[4]; 220 221 void sleep(int n) { 222 try { 223 Thread.sleep(n); 224 } catch (InterruptedException e) { 225 } 226 } 227 228 @Override 229 public synchronized void handle(HttpExchange t) 230 throws IOException { 231 int remotePort = t.getRemoteAddress().getPort(); 232 String result = "OK"; 233 234 int n = counter++; 235 /// First test 236 if (n < 4) { 237 ports[n] = remotePort; 238 } 239 if (n == 3) { 240 // check all values in ports[] are the same 241 if (ports[0] != ports[1] || ports[2] != ports[3] 242 || ports[0] != ports[2]) { 243 result = "Error " + Integer.toString(n); 244 System.out.println(result); 245 } 246 } 247 // Second test 248 if (n >= 4 && n < 8) { 249 // delay to ensure ports are different 250 sleep(500); 251 ports[n - 4] = remotePort; 252 } 253 if (n == 7) { 254 // should be all different 255 if (ports[0] == ports[1] || ports[2] == ports[3] 256 || ports[0] == ports[2]) { 257 result = "Error " + Integer.toString(n); 258 System.out.println(result); 259 System.out.printf("Ports: %d, %d, %d, %d\n", 260 ports[0], ports[1], ports[2], ports[3]); 261 } 262 // setup for third test 263 for (int i = 0; i < 4; i++) { 264 portSet.add(ports[i]); 265 } 266 } 267 // Third test 268 if (n > 7) { 269 // just check that port is one of the ones in portSet 270 if (!portSet.contains(remotePort)) { 271 System.out.println("UNEXPECTED REMOTE PORT " + remotePort); 272 result = "Error " + Integer.toString(n); 273 System.out.println(result); 274 } 275 } 276 byte[] buf = new byte[2048]; 277 278 try (InputStream is = t.getRequestBody()) { 279 while (is.read(buf) != -1) ; 280 } 281 t.sendResponseHeaders(200, result.length()); 282 OutputStream o = t.getResponseBody(); 283 o.write(result.getBytes("US-ASCII")); 284 t.close(); 285 } 286 } 287 288 static class DelayHandler implements HttpHandler { 289 290 CyclicBarrier bar1 = new CyclicBarrier(2); 291 CyclicBarrier bar2 = new CyclicBarrier(2); 292 CyclicBarrier bar3 = new CyclicBarrier(2); 293 294 CyclicBarrier barrier1() { 295 return bar1; 296 } 297 298 CyclicBarrier barrier2() { 299 return bar2; 300 } 301 302 @Override 303 public synchronized void handle(HttpExchange he) throws IOException { 304 byte[] buf = Util.readAll(he.getRequestBody()); 305 try { 306 bar1.await(); 307 bar2.await(); 308 } catch (InterruptedException | BrokenBarrierException e) { 309 } 310 he.sendResponseHeaders(200, -1); // will probably fail 311 he.close(); 312 } 313 } 314 }