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