Skip to content

Commit

Permalink
Got all RestServers to support HTTPS
Browse files Browse the repository at this point in the history
  • Loading branch information
danielbodart committed Oct 25, 2015
1 parent 2083787 commit 80f04a7
Show file tree
Hide file tree
Showing 14 changed files with 299 additions and 30 deletions.
46 changes: 32 additions & 14 deletions src/com/googlecode/utterlyidle/ServerConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.googlecode.utterlyidle;

import com.googlecode.totallylazy.Unchecked;
import com.googlecode.totallylazy.Option;
import com.googlecode.totallylazy.Uri;
import com.googlecode.utterlyidle.httpserver.RestServer;
import com.googlecode.utterlyidle.ssl.SSL;

import javax.net.ssl.SSLContext;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;

import static com.googlecode.totallylazy.Option.none;
import static com.googlecode.totallylazy.Option.some;
import static com.googlecode.totallylazy.Unchecked.cast;
import static com.googlecode.totallylazy.Uri.uri;
import static java.lang.Integer.valueOf;
Expand All @@ -28,33 +32,34 @@ public class ServerConfiguration {
public static final String DEFAULT_PORT = "0";
public static final String DEFAULT_CLASS = RestServer.class.getCanonicalName();

private final String protocol;
private final BasePath basePath;
private final int maxThreadNumber;
private final InetAddress bindAddress;
private final int port;
private final Class<? extends Server> serverClass;
private final Option<SSLContext> sslContext;

public ServerConfiguration(String protocol, BasePath basePath, int maxThreadNumber, InetAddress bindAddress, int port, Class<? extends Server> serverClass) {
this.protocol = protocol;
public ServerConfiguration(BasePath basePath, int maxThreadNumber, InetAddress bindAddress, int port, Class<? extends Server> serverClass, final Option<SSLContext> sslContext) {
this.basePath = basePath;
this.maxThreadNumber = maxThreadNumber;
this.bindAddress = bindAddress;
this.port = port;
this.serverClass = serverClass;
this.sslContext = sslContext;
}

public ServerConfiguration() {
this(DEFAULT_PROTOCOL, new BasePath(DEFAULT_BASE_PATH), Integer.parseInt(DEFAULT_THREAD_NUMBER), toInetAddress(DEFAULT_BIND_ADDRESS), Integer.parseInt(DEFAULT_PORT), toServer(DEFAULT_CLASS));
this(new BasePath(DEFAULT_BASE_PATH), Integer.parseInt(DEFAULT_THREAD_NUMBER), toInetAddress(DEFAULT_BIND_ADDRESS), Integer.parseInt(DEFAULT_PORT), toServer(DEFAULT_CLASS), none(SSLContext.class));
}

public ServerConfiguration(Properties properties) {
this(properties.getProperty(SERVER_PROTOCOL, DEFAULT_PROTOCOL),
this(
new BasePath(properties.getProperty(SERVER_BASE_PATH, DEFAULT_BASE_PATH)),
valueOf(properties.getProperty(MAX_THREAD_NUM, DEFAULT_THREAD_NUMBER)),
toInetAddress(properties.getProperty(SERVER_BIND_ADDRESS, DEFAULT_BIND_ADDRESS)),
valueOf(properties.getProperty(SERVER_PORT, DEFAULT_PORT)),
toServer(properties.getProperty(SERVER_CLASS, DEFAULT_CLASS)));
toServer(properties.getProperty(SERVER_CLASS, DEFAULT_CLASS)),
toSSLContext(properties.getProperty(SERVER_PROTOCOL, DEFAULT_PROTOCOL)));
}

public static ServerConfiguration defaultConfiguration() {
Expand All @@ -66,47 +71,60 @@ public BasePath basePath() {
}

public ServerConfiguration basePath(BasePath basePath) {
return new ServerConfiguration(protocol, basePath, maxThreadNumber, bindAddress, port, serverClass);
return new ServerConfiguration(basePath, maxThreadNumber, bindAddress, port, serverClass, sslContext);
}

public int maxThreadNumber() {
return maxThreadNumber;
}

public ServerConfiguration maxThreadNumber(int maxThreadNumber) {
return new ServerConfiguration(protocol, basePath, maxThreadNumber, bindAddress, port, serverClass);
return new ServerConfiguration(basePath, maxThreadNumber, bindAddress, port, serverClass, sslContext);
}

public Class<? extends Server> serverClass() {
return serverClass;
}

public ServerConfiguration serverClass(Class<? extends Server> serverClass) {
return new ServerConfiguration(protocol, basePath, maxThreadNumber, bindAddress, port, serverClass);
return new ServerConfiguration(basePath, maxThreadNumber, bindAddress, port, serverClass, sslContext);
}

public InetAddress bindAddress() {
return bindAddress;
}

public ServerConfiguration bindAddress(InetAddress bindAddress) {
return new ServerConfiguration(protocol, basePath, maxThreadNumber, bindAddress, port, serverClass);
return new ServerConfiguration(basePath, maxThreadNumber, bindAddress, port, serverClass, sslContext);
}

public int port() {
return port;
}

public ServerConfiguration port(int bindPort) {
return new ServerConfiguration(protocol, basePath, maxThreadNumber, bindAddress, bindPort, serverClass);
return new ServerConfiguration(basePath, maxThreadNumber, bindAddress, bindPort, serverClass, sslContext);
}

public String protocol() {
return protocol;
return sslContext.isDefined() ? Protocol.HTTPS : Protocol.HTTP;
}

public ServerConfiguration protocol(final String protocol) {
return new ServerConfiguration(protocol, basePath, maxThreadNumber, bindAddress, port, serverClass);
return new ServerConfiguration(basePath, maxThreadNumber, bindAddress, port, serverClass, toSSLContext(protocol));
}

public Option<SSLContext> sslContext() {
return sslContext;
}

public ServerConfiguration sslContext(final SSLContext sslContext) {
return new ServerConfiguration(basePath, maxThreadNumber, bindAddress, port, serverClass, some(sslContext));
}

private static Option<SSLContext> toSSLContext(String protocol){
if(protocol.equals(Protocol.HTTPS)) return some(SSL.sslContext());
return none();
}

private static InetAddress toInetAddress(final String address) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.io.Closeable;
import java.io.File;
Expand Down Expand Up @@ -104,6 +105,10 @@ public ClientHttpHandler(int connectTimeoutMillis, int readTimeoutMillis, ProxyF
this(connectTimeoutMillis, readTimeoutMillis, proxies, HttpsURLConnection.getDefaultHostnameVerifier(), HttpsURLConnection.getDefaultSSLSocketFactory());
}

public ClientHttpHandler(int connectTimeoutMillis, int readTimeoutMillis, ProxyFor proxies, HostnameVerifier hostnameVerifier, final SSLContext sslContext) {
this(connectTimeoutMillis, readTimeoutMillis, proxies, hostnameVerifier, sslContext.getSocketFactory());
}

public ClientHttpHandler(int connectTimeoutMillis, int readTimeoutMillis, ProxyFor proxies, HostnameVerifier hostnameVerifier, final SSLSocketFactory sslSocketFactory) {
this.connectTimeoutMillis = connectTimeoutMillis;
this.readTimeoutMillis = readTimeoutMillis;
Expand Down
7 changes: 3 additions & 4 deletions src/com/googlecode/utterlyidle/httpserver/RestHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import com.googlecode.totallylazy.Value;
import com.googlecode.utterlyidle.Application;
import com.googlecode.utterlyidle.HttpHeaders;
import com.googlecode.utterlyidle.Protocol;
import com.googlecode.utterlyidle.Request;
import com.googlecode.utterlyidle.Requests;
import com.googlecode.utterlyidle.Response;
import com.googlecode.utterlyidle.ResponseBuilder;
import com.googlecode.utterlyidle.Status;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpsExchange;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
Expand Down Expand Up @@ -63,13 +65,10 @@ private Request request(HttpExchange httpExchange) {
);
return requestEnricher(
clientAddress(httpExchange.getRemoteAddress().getAddress()),
extractScheme(httpExchange.getProtocol()))
httpExchange instanceof HttpsExchange ? Protocol.HTTPS : Protocol.HTTP)
.enrich(request);
}

private String extractScheme(final String protocol) {
return protocol.toLowerCase().split("/")[0];
}

private Response exceptionResponse(Request request, final Exception e) throws IOException {
System.err.println(String.format("%s %s -> %s", request.method(), request.uri(), e));
Expand Down
18 changes: 15 additions & 3 deletions src/com/googlecode/utterlyidle/httpserver/RestServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
import com.googlecode.totallylazy.Uri;
import com.googlecode.utterlyidle.Application;
import com.googlecode.utterlyidle.ApplicationBuilder;
import com.googlecode.utterlyidle.Protocol;
import com.googlecode.utterlyidle.Server;
import com.googlecode.utterlyidle.ServerConfiguration;
import com.googlecode.utterlyidle.examples.HelloWorldApplication;
import com.googlecode.utterlyidle.services.Service;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;

import java.io.IOException;
import java.net.InetSocketAddress;
Expand Down Expand Up @@ -57,14 +60,23 @@ private HttpServer startApp(Application application, ServerConfiguration configu
}

private HttpServer startUpServer(Application application, ServerConfiguration configuration) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(configuration.bindAddress(), configuration.port()), 0);
server.createContext(configuration.basePath().toString(),
new RestHandler(application));
HttpServer server = createServer(configuration);
server.createContext(configuration.basePath().toString(), new RestHandler(application));
executorService = newFixedThreadPool(configuration.maxThreadNumber(), getClass());
server.setExecutor(executorService);
server.start();
ServerConfiguration updatedConfiguration = configuration.port(server.getAddress().getPort());
uri = updatedConfiguration.toUrl();
return server;
}

private HttpServer createServer(final ServerConfiguration configuration) throws IOException {
InetSocketAddress address = new InetSocketAddress(configuration.bindAddress(), configuration.port());
if(configuration.protocol().equals(Protocol.HTTPS)) {
HttpsServer server = HttpsServer.create(address, 0);
server.setHttpsConfigurator(new HttpsConfigurator(configuration.sslContext().get()));
return server;
}
return HttpServer.create(address, 0);
}
}
23 changes: 20 additions & 3 deletions src/com/googlecode/utterlyidle/jetty/RestServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@
import com.googlecode.utterlyidle.Application;
import com.googlecode.utterlyidle.ApplicationBuilder;
import com.googlecode.utterlyidle.BasePath;
import com.googlecode.utterlyidle.Protocol;
import com.googlecode.utterlyidle.ServerConfiguration;
import com.googlecode.utterlyidle.examples.HelloWorldApplication;
import com.googlecode.utterlyidle.services.Service;
import com.googlecode.utterlyidle.servlet.ApplicationServlet;
import com.googlecode.utterlyidle.servlet.ServletModule;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.security.SslSocketConnector;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.thread.QueuedThreadPool;

import javax.net.ssl.SSLServerSocketFactory;
import javax.servlet.ServletContext;
import java.io.IOException;

Expand Down Expand Up @@ -117,14 +121,27 @@ public Context call(Server server) throws Exception {

private Server createServer(ServerConfiguration serverConfig) {
Server server = new Server();
SelectChannelConnector selectChannelConnector = new SelectChannelConnector();
selectChannelConnector.setPort(serverConfig.port());
selectChannelConnector.setHost(serverConfig.bindAddress().getHostAddress());
org.mortbay.jetty.Connector selectChannelConnector = connector(serverConfig);
server.addConnector(selectChannelConnector);
server.setThreadPool(new QueuedThreadPool(serverConfig.maxThreadNumber()));
return server;
}

private Connector connector(final ServerConfiguration serverConfig) {
if(serverConfig.protocol().equals(Protocol.HTTPS)){
return new SslSocketConnector(){
@Override
protected SSLServerSocketFactory createFactory() throws Exception {
return configuration.sslContext().get().getServerSocketFactory();
}
};
}
SelectChannelConnector selectChannelConnector = new SelectChannelConnector();
selectChannelConnector.setPort(serverConfig.port());
selectChannelConnector.setHost(serverConfig.bindAddress().getHostAddress());
return selectChannelConnector;
}

private int portNumber(Server server) {
return sequence(server.getConnectors()).head().getLocalPort();
}
Expand Down
17 changes: 16 additions & 1 deletion src/com/googlecode/utterlyidle/jetty/eclipse/RestServer.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.googlecode.utterlyidle.jetty.eclipse;

import com.googlecode.totallylazy.Callable1;
import com.googlecode.totallylazy.Option;
import com.googlecode.totallylazy.Uri;
import com.googlecode.utterlyidle.Application;
import com.googlecode.utterlyidle.ApplicationBuilder;
Expand All @@ -13,8 +15,10 @@
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;

import javax.net.ssl.SSLContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
Expand Down Expand Up @@ -70,13 +74,24 @@ public void handle(String target, Request baseRequest, HttpServletRequest servle

protected Server createServer(ServerConfiguration serverConfig) {
Server server = new Server(new QueuedThreadPool(serverConfig.maxThreadNumber()));
ServerConnector serverConnector = new ServerConnector(server, new HttpConnectionFactory());
ServerConnector serverConnector = new ServerConnector(server, sslContextFactory(serverConfig).getOrNull(), new HttpConnectionFactory());
serverConnector.setPort(serverConfig.port());
serverConnector.setHost(serverConfig.bindAddress().getHostAddress());
server.addConnector(serverConnector);
return server;
}

private Option<SslContextFactory> sslContextFactory(final ServerConfiguration serverConfig) {
return serverConfig.sslContext().map(new Callable1<SSLContext, SslContextFactory>() {
@Override
public SslContextFactory call(final SSLContext context) throws Exception {
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setSslContext(context);
return sslContextFactory;
}
});
}

@Override
public Application application() {
return application;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ private Connection startApp(Application application, ServerConfiguration configu
private SocketConnection startUpApp(Application application, ServerConfiguration configuration) throws IOException {
Container container = new RestContainer(application);
SocketConnection connection = new SocketConnection(new ContainerSocketProcessor(container, configuration.maxThreadNumber()));
InetSocketAddress socketAddress = (InetSocketAddress) connection.connect(new InetSocketAddress(configuration.bindAddress(), configuration.port()));
InetSocketAddress socketAddress = (InetSocketAddress) connection.connect(new InetSocketAddress(configuration.bindAddress(), configuration.port()),
configuration.sslContext().getOrNull());

ServerConfiguration updatedConfiguration = configuration.port(socketAddress.getPort());
uri = updatedConfiguration.toUrl();
Expand Down
Loading

0 comments on commit 80f04a7

Please sign in to comment.