blob: a0d6e9ac9c760d661db5fb3959e41beaa0ce9f06 [file] [log] [blame]
/*
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* library /lib/testlibrary/ /
* build jdk.testlibrary.SimpleSSLContext ProxyServer EchoHandler
* compile ../../../com/sun/net/httpserver/LogFilter.java
* compile ../../../com/sun/net/httpserver/FileServerHandler.java
*/
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLContext;
import jdk.testlibrary.SimpleSSLContext;
public class LightWeightHttpServer {
static SSLContext ctx;
static HttpServer httpServer;
static HttpsServer httpsServer;
static ExecutorService executor;
static int port;
static int httpsport;
static String httproot;
static String httpsroot;
static ProxyServer proxy;
static int proxyPort;
static RedirectErrorHandler redirectErrorHandler, redirectErrorHandlerSecure;
static RedirectHandler redirectHandler, redirectHandlerSecure;
static DelayHandler delayHandler;
static final String midSizedFilename = "/files/notsobigfile.txt";
static final String smallFilename = "/files/smallfile.txt";
static Path midSizedFile;
static Path smallFile;
static String fileroot;
public static void initServer() throws IOException {
Logger logger = Logger.getLogger("com.sun.net.httpserver");
ConsoleHandler ch = new ConsoleHandler();
logger.setLevel(Level.ALL);
ch.setLevel(Level.ALL);
logger.addHandler(ch);
String root = System.getProperty("test.src") + "/docs";
InetSocketAddress addr = new InetSocketAddress(0);
httpServer = HttpServer.create(addr, 0);
if (httpServer instanceof HttpsServer) {
throw new RuntimeException("should not be httpsserver");
}
httpsServer = HttpsServer.create(addr, 0);
HttpHandler h = new FileServerHandler(root);
HttpContext c1 = httpServer.createContext("/files", h);
HttpContext c2 = httpsServer.createContext("/files", h);
HttpContext c3 = httpServer.createContext("/echo", new EchoHandler());
redirectHandler = new RedirectHandler("/redirect");
redirectHandlerSecure = new RedirectHandler("/redirect");
HttpContext c4 = httpServer.createContext("/redirect", redirectHandler);
HttpContext c41 = httpsServer.createContext("/redirect", redirectHandlerSecure);
HttpContext c5 = httpsServer.createContext("/echo", new EchoHandler());
HttpContext c6 = httpServer.createContext("/keepalive", new KeepAliveHandler());
redirectErrorHandler = new RedirectErrorHandler("/redirecterror");
redirectErrorHandlerSecure = new RedirectErrorHandler("/redirecterror");
HttpContext c7 = httpServer.createContext("/redirecterror", redirectErrorHandler);
HttpContext c71 = httpsServer.createContext("/redirecterror", redirectErrorHandlerSecure);
delayHandler = new DelayHandler();
HttpContext c8 = httpServer.createContext("/delay", delayHandler);
HttpContext c81 = httpsServer.createContext("/delay", delayHandler);
executor = Executors.newCachedThreadPool();
httpServer.setExecutor(executor);
httpsServer.setExecutor(executor);
ctx = new SimpleSSLContext().get();
httpsServer.setHttpsConfigurator(new HttpsConfigurator(ctx));
httpServer.start();
httpsServer.start();
port = httpServer.getAddress().getPort();
System.out.println("HTTP server port = " + port);
httpsport = httpsServer.getAddress().getPort();
System.out.println("HTTPS server port = " + httpsport);
httproot = "http://127.0.0.1:" + port + "/";
httpsroot = "https://127.0.0.1:" + httpsport + "/";
proxy = new ProxyServer(0, false);
proxyPort = proxy.getPort();
System.out.println("Proxy port = " + proxyPort);
}
public static void stop() throws IOException {
if (httpServer != null) {
httpServer.stop(0);
}
if (httpsServer != null) {
httpsServer.stop(0);
}
if (proxy != null) {
proxy.close();
}
if (executor != null) {
executor.shutdownNow();
}
}
static class RedirectErrorHandler implements HttpHandler {
String root;
volatile int count = 1;
RedirectErrorHandler(String root) {
this.root = root;
}
synchronized int count() {
return count;
}
synchronized void increment() {
count++;
}
@Override
public synchronized void handle(HttpExchange t)
throws IOException {
byte[] buf = new byte[2048];
try (InputStream is = t.getRequestBody()) {
while (is.read(buf) != -1) ;
}
Headers map = t.getResponseHeaders();
String redirect = root + "/foo/" + Integer.toString(count);
increment();
map.add("Location", redirect);
t.sendResponseHeaders(301, -1);
t.close();
}
}
static class RedirectHandler implements HttpHandler {
String root;
volatile int count = 0;
RedirectHandler(String root) {
this.root = root;
}
@Override
public synchronized void handle(HttpExchange t)
throws IOException {
byte[] buf = new byte[2048];
try (InputStream is = t.getRequestBody()) {
while (is.read(buf) != -1) ;
}
Headers map = t.getResponseHeaders();
if (count++ < 1) {
map.add("Location", root + "/foo/" + count);
} else {
map.add("Location", SmokeTest.midSizedFilename);
}
t.sendResponseHeaders(301, -1);
t.close();
}
int count() {
return count;
}
void reset() {
count = 0;
}
}
static class KeepAliveHandler implements HttpHandler {
volatile int counter = 0;
HashSet<Integer> portSet = new HashSet<>();
volatile int[] ports = new int[4];
void sleep(int n) {
try {
Thread.sleep(n);
} catch (InterruptedException e) {
}
}
@Override
public synchronized void handle(HttpExchange t)
throws IOException {
int remotePort = t.getRemoteAddress().getPort();
String result = "OK";
int n = counter++;
/// First test
if (n < 4) {
ports[n] = remotePort;
}
if (n == 3) {
// check all values in ports[] are the same
if (ports[0] != ports[1] || ports[2] != ports[3]
|| ports[0] != ports[2]) {
result = "Error " + Integer.toString(n);
System.out.println(result);
}
}
// Second test
if (n >= 4 && n < 8) {
// delay to ensure ports are different
sleep(500);
ports[n - 4] = remotePort;
}
if (n == 7) {
// should be all different
if (ports[0] == ports[1] || ports[2] == ports[3]
|| ports[0] == ports[2]) {
result = "Error " + Integer.toString(n);
System.out.println(result);
System.out.printf("Ports: %d, %d, %d, %d\n",
ports[0], ports[1], ports[2], ports[3]);
}
// setup for third test
for (int i = 0; i < 4; i++) {
portSet.add(ports[i]);
}
}
// Third test
if (n > 7) {
// just check that port is one of the ones in portSet
if (!portSet.contains(remotePort)) {
System.out.println("UNEXPECTED REMOTE PORT " + remotePort);
result = "Error " + Integer.toString(n);
System.out.println(result);
}
}
byte[] buf = new byte[2048];
try (InputStream is = t.getRequestBody()) {
while (is.read(buf) != -1) ;
}
t.sendResponseHeaders(200, result.length());
OutputStream o = t.getResponseBody();
o.write(result.getBytes("US-ASCII"));
t.close();
}
}
static class DelayHandler implements HttpHandler {
CyclicBarrier bar1 = new CyclicBarrier(2);
CyclicBarrier bar2 = new CyclicBarrier(2);
CyclicBarrier bar3 = new CyclicBarrier(2);
CyclicBarrier barrier1() {
return bar1;
}
CyclicBarrier barrier2() {
return bar2;
}
@Override
public synchronized void handle(HttpExchange he) throws IOException {
byte[] buf = Util.readAll(he.getRequestBody());
try {
bar1.await();
bar2.await();
} catch (InterruptedException | BrokenBarrierException e) {
}
he.sendResponseHeaders(200, -1); // will probably fail
he.close();
}
}
}