import java.io.IOException;
import java.net.InetSocketAddress;
+import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
+import javax.net.ssl.SSLContext;
import javax.servlet.ServletException;
import javax.websocket.server.ServerContainer;
import org.argeo.api.cms.CmsState;
import org.argeo.cms.CmsDeployProperty;
import org.argeo.cms.http.server.HttpServerUtils;
+import org.eclipse.jetty.ee8.servlet.ServletContextHandler;
import org.eclipse.jetty.http.UriCompliance;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
public class JettyHttpServer extends HttpsServer {
private final static CmsLog log = CmsLog.getLog(JettyHttpServer.class);
- private static final int DEFAULT_IDLE_TIMEOUT = 30000;
+ /** Long timeout since our users may have poor connections. */
+ private static final int DEFAULT_IDLE_TIMEOUT = 120 * 1000;
private Server server;
@Override
public void start() {
+ String httpPortStr = getDeployProperty(CmsDeployProperty.HTTP_PORT);
+ String httpsPortStr = getDeployProperty(CmsDeployProperty.HTTPS_PORT);
+ if (httpPortStr != null && httpsPortStr != null)
+ throw new IllegalArgumentException("Either an HTTP or an HTTPS port should be configured, not both");
+ if (httpPortStr == null && httpsPortStr == null) {
+ log.warn("Neither an HTTP or an HTTPS port was configured, not starting Jetty");
+ }
+
+ /// TODO make it more generic
+ String httpHost = getDeployProperty(CmsDeployProperty.HOST);
+
try {
ThreadPool threadPool = null;
server = new Server(threadPool);
- configureConnectors();
+ configureConnectors(httpPortStr, httpsPortStr, httpHost);
if (httpConnector != null) {
httpConnector.open();
//
// Addresses
- String httpHost = getDeployProperty(CmsDeployProperty.HOST);
String fallBackHostname = cmsState != null ? cmsState.getHostname() : "::1";
if (httpConnector != null) {
httpAddress = new InetSocketAddress(httpHost != null ? httpHost : fallBackHostname,
}
}
- protected void configureConnectors() {
- String httpPortStr = getDeployProperty(CmsDeployProperty.HTTP_PORT);
- String httpsPortStr = getDeployProperty(CmsDeployProperty.HTTPS_PORT);
- if (httpPortStr != null && httpsPortStr != null)
- throw new IllegalArgumentException("Either an HTTP or an HTTPS port should be configured, not both");
- if (httpPortStr == null && httpsPortStr == null)
- throw new IllegalArgumentException("Neither an HTTP or HTTPS port was configured");
-
- /// TODO make it more generic
- String httpHost = getDeployProperty(CmsDeployProperty.HOST);
+ protected void configureConnectors(String httpPortStr, String httpsPortStr, String httpHost) {
// try {
if (httpPortStr != null || httpsPortStr != null) {
}
if (httpsEnabled) {
+ if (httpsConfigurator == null) {
+ // we make sure that an HttpSConfigurator is set, so that clients can detect
+ // whether this server is HTTP or HTTPS
+ try {
+ httpsConfigurator = new HttpsConfigurator(SSLContext.getDefault());
+ } catch (NoSuchAlgorithmException e) {
+ throw new IllegalStateException("Cannot initalise SSL Context", e);
+ }
+ }
+
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
// sslContextFactory.setKeyStore(KeyS)
int httpsPort = Integer.parseInt(httpsPortStr);
httpsConnector.setPort(httpsPort);
httpsConnector.setHost(httpHost);
+ httpsConnector.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
}
}
}
server.stop();
// TODO delete temp dir
started = false;
+ log.debug(() -> "Stopped Jetty server");
} catch (Exception e) {
log.error("Cannot stop Jetty HTTP server", e);
}
@Override
public synchronized void removeContext(String path) throws IllegalArgumentException {
+ if (!path.endsWith("/"))
+ path = path + "/";
if (!contexts.containsKey(path))
throw new IllegalArgumentException("Context " + path + " does not exist");
JettyHttpContext httpContext = contexts.remove(path);
if (httpContext instanceof ContextHandlerHttpContext contextHandlerHttpContext) {
// TODO stop handler first?
- contextHandlerCollection.removeHandler(contextHandlerHttpContext.getServletContextHandler());
+ // FIXME understand compatibility with Jetty 12
+ // contextHandlerCollection.removeHandler(contextHandlerHttpContext.getServletContextHandler());
+ } else {
+ // FIXME apparently servlets cannot be removed in Jetty, we should replace the
+ // handler
}
}
}
private String httpPortsMsg() {
+ String hostStr = getHost();
+ hostStr = hostStr == null ? "*:" : hostStr + ":";
+ return (httpConnector != null ? "# HTTP " + hostStr + getHttpPort() + " " : "")
+ + (httpsConnector != null ? "# HTTPS " + hostStr + getHttpsPort() : "");
+ }
- return (httpConnector != null ? "HTTP " + getHttpPort() + " " : "")
- + (httpsConnector != null ? "HTTPS " + getHttpsPort() : "");
+ public String getHost() {
+ if (httpConnector == null)
+ return null;
+ return httpConnector.getHost();
}
public Integer getHttpPort() {