package com.netflix.governator.guice.jetty;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.util.Modules;
import com.netflix.governator.InjectorBuilder;
import com.netflix.governator.LifecycleInjector;
import com.netflix.governator.ShutdownHookModule;
import com.netflix.governator.guice.jetty.resources1.SampleResource;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.junit.Assert;
import org.junit.Test;
import javax.annotation.PreDestroy;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
public class JettyServerTest {
static class Foo {
private boolean shutdownCalled;
@PreDestroy
void shutdown() {
shutdownCalled = true;
}
};
@Test
public void confirmShutdownSequence() throws InterruptedException, MalformedURLException, IOException {
// Create the injector and autostart Jetty
LifecycleInjector injector = InjectorBuilder.fromModules(
new SampleServletModule(),
new ShutdownHookModule(),
Modules.override(new JettyModule())
.with(new AbstractModule() {
@Override
protected void configure() {
bind(Foo.class).asEagerSingleton();
}
@Provides
JettyConfig getConfig() {
// Use emphemeral ports
return new DefaultJettyConfig().setPort(0);
}
}))
.createInjector();
Foo foo = injector.getInstance(Foo.class);
// Determine the emphermal port from jetty
Server server = injector.getInstance(Server.class);
int port = ((ServerConnector)server.getConnectors()[0]).getLocalPort();
SampleResource resource = injector.getInstance(SampleResource.class);
Assert.assertEquals(1, resource.getPostConstructCount());
Assert.assertEquals(0, resource.getPreDestroyCount());
System.out.println("Listening on port : "+ port);
URL url = new URL(String.format("http://localhost:%d/kill", port));
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
try {
conn.getResponseCode();
}
catch (Exception e) {
}
injector.awaitTermination();
Assert.assertTrue(foo.shutdownCalled);
Assert.assertEquals(1, resource.getPostConstructCount());
Assert.assertEquals(1, resource.getPreDestroyCount());
}
@Test
public void testConnectorBinding() throws Exception {
LifecycleInjector injector = InjectorBuilder.fromModules(
new SampleServletModule(),
new ShutdownHookModule(),
Modules.override(new JettyModule())
.with(new AbstractModule() {
@Override
protected void configure() {
}
@Provides
JettyConfig getConfig() {
// Use ephemeral ports
return new DefaultJettyConfig().setPort(0);
}
}),
new JettySslModule()
).createInjector();
Server server = injector.getInstance(Server.class);
Assert.assertEquals(2, server.getConnectors().length);
KeyStore keyStore = injector.getInstance(KeyStore.class);
int port = ((ServerConnector)server.getConnectors()[0]).getLocalPort();
int sslPort = ((ServerConnector)server.getConnectors()[1]).getLocalPort();
// Do a plaintext GET and verify that the default connector works
String response = doGet(String.format("http://localhost:%d/", port), null);
Assert.assertTrue(response.startsWith("hello "));
// Do an SSL GET and verify the response is valid
response = doGet(String.format("https://localhost:%d/", sslPort), keyStore);
Assert.assertTrue(response.startsWith("hello "));
injector.close();
}
private static String doGet(String url, KeyStore sslTrustStore) throws Exception {
URLConnection urlConnection = new URL(url).openConnection();
if (sslTrustStore != null) {
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(sslTrustStore);
sslContext.init(null, tmf.getTrustManagers(), null);
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) urlConnection;
httpsURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
}
try (InputStream inputStream = urlConnection.getInputStream()) {
byte[] buffer = new byte[4096];
int n = inputStream.read(buffer);
return new String(buffer, 0, n, StandardCharsets.UTF_8);
}
}
}