-
-
Save natros/a9f8eaba60e1e5de80b7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A qualifier for the server http port. | |
* | |
* @author [email protected] (Ben Manes) | |
*/ | |
@BindingAnnotation | |
@Retention(RUNTIME) | |
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) | |
public @interface HttpPort {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A qualifier for the server https port. | |
* | |
* @author [email protected] (Ben Manes) | |
*/ | |
@BindingAnnotation | |
@Retention(RUNTIME) | |
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) | |
public @interface HttpsPort {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A module that configures the Jetty webserver. | |
* | |
* @author [email protected] (Ben Manes) | |
*/ | |
public final class JettyModule extends ServletModule { | |
final Config config = ConfigFactory.load().getConfig(getClass().getPackage().getName()); | |
@Override | |
protected void configureServlets() { | |
configureAdminServlet(); | |
configureMetricsFilter(); | |
install(new MetricsModule()); | |
bind(Server.class).toProvider(ServerProvider.class); | |
} | |
@Provides @HttpPort | |
OptionalInt providesHttpPort() { | |
return config.hasPath("http_port") | |
? OptionalInt.of(config.getInt("http_port")) | |
: OptionalInt.empty(); | |
} | |
@Provides @HttpsPort | |
OptionalInt providesHttpsPort() { | |
return config.hasPath("https_port") | |
? OptionalInt.of(config.getInt("https_port")) | |
: OptionalInt.empty(); | |
} | |
private void configureMetricsFilter() { | |
filter("/*").through(InstrumentedFilter.class); | |
bind(InstrumentedFilter.class).in(Singleton.class); | |
Multibinder.newSetBinder(binder(), ServletContextListener.class) | |
.addBinding().toInstance(new InstrumentedFilterContextListener() { | |
@Override protected MetricRegistry getMetricRegistry() { | |
return SharedRegistry.metricRegistry(); | |
} | |
}); | |
Multibinder.newSetBinder(binder(), ServletContextListener.class) | |
.addBinding().toInstance(new HealthCheckServlet.ContextListener() { | |
@Override protected HealthCheckRegistry getHealthCheckRegistry() { | |
return SharedRegistry.healthCheckRegistry(); | |
} | |
}); | |
Multibinder.newSetBinder(binder(), ServletContextListener.class) | |
.addBinding().toInstance(new MetricsServlet.ContextListener() { | |
@Override protected MetricRegistry getMetricRegistry() { | |
return SharedRegistry.metricRegistry(); | |
} | |
}); | |
} | |
private void configureAdminServlet() { | |
bind(AdminServlet.class).asEagerSingleton(); | |
Map<String, String> initParams = ImmutableMap.of( | |
"healthcheck-uri", AdminServlet.DEFAULT_HEALTHCHECK_URI, | |
"threads-uri", AdminServlet.DEFAULT_THREADS_URI, | |
"metrics-uri",AdminServlet.DEFAULT_METRICS_URI, | |
"ping-uri", AdminServlet.DEFAULT_PING_URI); | |
serve("/admin/*").with(AdminServlet.class, initParams); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Provides a fully configured Jetty server. | |
* | |
* @author [email protected] (Ben Manes) | |
*/ | |
final class ServerProvider implements Provider<Server> { | |
private final Config config = ConfigFactory.load().getConfig(getClass().getPackage().getName()); | |
private final Set<ServletContextListener> listeners; | |
private final OptionalInt httpsPort; | |
private final OptionalInt httpPort; | |
@Inject | |
public ServerProvider(@HttpPort OptionalInt httpPort, @HttpsPort OptionalInt httpsPort, | |
Set<ServletContextListener> 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<Connector> 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<String> getProtocols() { | |
return delegate.getProtocols(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment