/** * Provides a fully configured Jetty server. * * @author ben.manes@gmail.com (Ben Manes) */ final class ServerProvider implements Provider { private final Config config = ConfigFactory.load().getConfig(getClass().getPackage().getName()); private final Set listeners; private final OptionalInt httpsPort; private final OptionalInt httpPort; @Inject public ServerProvider(@HttpPort OptionalInt httpPort, @HttpsPort OptionalInt httpsPort, Set listeners) { this.listeners = listeners; this.httpsPort = httpsPort; this.httpPort = httpPort; } @Override public Server get() { Server server = new Server(new InstrumentedQueuedThreadPool(SharedRegistry.metricRegistry())); addConnectors(server); addHandler(server); configure(server); return server; } private void configure(Server server) { server.setRequestLog(new Slf4jRequestLog()); } private void addHandler(Server server) { InstrumentedHandler instrumented = new InstrumentedHandler(SharedRegistry.metricRegistry()); ServletContextHandler handler = new ServletContextHandler(instrumented, "/"); handler.addFilter(GuiceFilter.class, "/*", null); handler.addServlet(DefaultServlet.class, "/"); for (ServletContextListener listener : listeners) { handler.addEventListener(listener); } server.setHandler(instrumented); } private void addConnectors(Server server) { checkState(httpPort.isPresent() || httpsPort.isPresent(), "No http/s port specified"); List connectors = new ArrayList<>(); String host = config.hasPath("host") ? config.getString("host") : null; if (httpPort.isPresent()) { connectors.add(newHttpConnector(server, host)); } if (httpsPort.isPresent()) { connectors.add(newHttpsConnector(server, host)); } server.setConnectors(connectors.toArray(new Connector[connectors.size()])); } private ServerConnector newHttpConnector(Server server, String host) { HttpConfiguration httpConfig = new HttpConfiguration(); if (httpsPort.isPresent()) { httpConfig.setSecurePort(httpsPort.getAsInt()); } ServerConnector http = new ServerConnector(server, new ProtocolAwareInstrumentedConnectionFactory( new HttpConnectionFactory(httpConfig), "http.connection")); http.setPort(httpPort.getAsInt()); http.setHost(host); return http; } private ServerConnector newHttpsConnector(Server server, String host) { HttpConfiguration httpsConfig = new HttpConfiguration(); httpsConfig.addCustomizer(new SecureRequestCustomizer()); ServerConnector https = new ServerConnector(server, new SslConnectionFactory(newSslContextFactory(), "http/1.1"), new ProtocolAwareInstrumentedConnectionFactory( new HttpConnectionFactory(httpsConfig), "https.connection")); https.setPort(httpsPort.getAsInt()); https.setHost(host); return https; } private SslContextFactory newSslContextFactory() { SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(config.getString("key_store.path")); sslContextFactory.setKeyStorePassword(config.getString("key_store.password")); if (config.hasPath("key_store.manager_password")) { sslContextFactory.setKeyManagerPassword(config.getString("key_store.manager_password")); } return sslContextFactory; } private static final class ProtocolAwareInstrumentedConnectionFactory extends InstrumentedConnectionFactory { final ConnectionFactory delegate; ProtocolAwareInstrumentedConnectionFactory(ConnectionFactory delegate, String timerName) { super(delegate, SharedRegistry.metricRegistry().timer(timerName)); this.delegate = delegate; } @Override public List getProtocols() { return delegate.getProtocols(); } } }