feat(test-common): Add HTTPS and HTTP2 support to EchoServerVertx.
MODIFY
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/connector/ConnectorFactory.java
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/connector/ConnectorFactory.java
*/
package io.apiman.gateway.platforms.vertx3.connector;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
import io.apiman.common.config.options.TLSOptions;
import io.apiman.gateway.engine.IApiConnector;
import io.apiman.gateway.engine.IConnectorFactory;
@@ -33,10 +36,6 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-
/**
* Create Vert.x connectors to the enable apiman to connect to a backend API.
*
@@ -54,7 +53,7 @@ public class ConnectorFactory implements IConnectorFactory {
private TLSOptions tlsOptions;
private LoadingCache<HttpConnectorOptions, HttpClient> clientCache = CacheBuilder.newBuilder()
// TODO make this tuneable.
- .maximumSize(500)
+ .maximumSize(2000)
// Close any evicted connections.
.<HttpConnectorOptions, HttpClient>removalListener(eviction -> eviction.getValue().close())
// Either grab from cache or build new (which will be cached automatically).

MODIFY
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/connector/HttpConnector.java
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/connector/HttpConnector.java
@@ -54,7 +54,7 @@ import java.util.Map.Entry;
import java.util.Set;
/**
- * A vert.x-based HTTP connector; implementing both {@link ISignalReadStream} and {@link ISignalWriteStream}.
+ * A Vert.x-based HTTP connector; implementing both {@link ISignalReadStream} and {@link ISignalWriteStream}.
*
* Its {@link ISignalWriteStream} elements are valid immediately and its {@link ISignalReadStream} is sent as
* an event to the provided {@link #resultHandler} when once it has reached a valid state. Hence, it is safe
@@ -160,8 +160,8 @@ class HttpConnector implements IApiConnectionResponse, IApiConnection {
private void doConnection() {
String endpoint = ApimanPathUtils.join(apiPath, destination + queryParams(apiRequest.getQueryParams()));
- logger.debug(String.format("Connecting to %s | port: %d verb: %s path: %s", apiHost, apiPort,
- HttpMethod.valueOf(apiRequest.getType()), endpoint));
+ logger.debug("Connecting to {0} | port: {1} verb: {2} path: {3}", apiHost, apiPort,
+ HttpMethod.valueOf(apiRequest.getType()), endpoint);
clientRequest = client.request(HttpMethod.valueOf(apiRequest.getType()),
apiPort,

MODIFY
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/HttpGatewayVerticle.java
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/HttpGatewayVerticle.java
@@ -43,7 +43,7 @@ public class HttpGatewayVerticle extends ApimanVerticleWithEngine {
// Load any provided configuration into the HttpServerOptions.
JsonObject httpServerOptionsJson = apimanConfig.getVerticleConfig(verticleType().name())
- .getJsonObject("httpServerOptions", new JsonObject());
+ .getJsonObject("httpServerOptions", new JsonObject()); //$NON-NLS-1$
InheritingHttpServerOptionsConverter.fromJson(httpServerOptionsJson, httpServerOptions);
vertx.createHttpServer(httpServerOptions)

MODIFY
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/HttpsGatewayVerticle.java
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/HttpsGatewayVerticle.java
@@ -60,7 +60,7 @@ public class HttpsGatewayVerticle extends ApimanVerticleWithEngine {
// Load any provided configuration into the HttpServerOptions.
JsonObject httpServerOptionsJson = apimanConfig.getVerticleConfig(verticleType().name())
- .getJsonObject("httpServerOptions", new JsonObject());
+ .getJsonObject("httpServerOptions", new JsonObject()); //$NON-NLS-1$
InheritingHttpServerOptionsConverter.fromJson(httpServerOptionsJson, httpsServerOptions);
vertx.createHttpServer(httpsServerOptions)

MODIFY
test/common/src/main/java/io/apiman/test/common/echo/EchoServerVertx.java
test/common/src/main/java/io/apiman/test/common/echo/EchoServerVertx.java
@@ -20,15 +20,26 @@ import io.apiman.common.util.SimpleStringUtils;
import io.apiman.gateway.engine.beans.EngineErrorResponse;
import io.apiman.test.common.mock.EchoResponse;
import io.vertx.core.AbstractVerticle;
+import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
import io.vertx.core.buffer.Buffer;
+import io.vertx.core.http.HttpServer;
+import io.vertx.core.http.HttpServerOptions;
+import io.vertx.core.http.HttpServerOptionsConverter;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.logging.Logger;
+import io.vertx.core.logging.LoggerFactory;
+import io.vertx.core.net.JdkSSLEngineOptions;
+import io.vertx.core.net.JksOptions;
import io.vertx.core.streams.WriteStream;
+import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
@@ -62,6 +73,7 @@ import com.fasterxml.jackson.databind.SerializationFeature;
*/
@SuppressWarnings("nls")
public class EchoServerVertx extends AbstractVerticle {
+ private Logger log = LoggerFactory.getLogger(EchoServerVertx.class);
private static ObjectMapper jsonMapper = new ObjectMapper();
static {
@@ -78,20 +90,61 @@ public class EchoServerVertx extends AbstractVerticle {
}
private long counter = 0L;
+ private int toStart = 2;
@Override
public void start(Future<Void> startFuture) {
- int port = NumberUtils.toInt(System.getProperty("io.apiman.test.common.echo.port"), 9999);
- vertx.createHttpServer()
+ int port = NumberUtils.toInt(System.getProperty("io.apiman.test.common.echo.port"), 9998);
+ HttpServerOptions httpServerOptions = getHttpServerOptions();
+ HttpServerOptions httpsServerOptions = getHttpsServerOptions()
+ .setSsl(true)
+ .setKeyStoreOptions(getKeystore())
+ .setTrustStoreOptions(getTrustStore());
+
+ // Plain HTTP server
+ vertx.createHttpServer(httpServerOptions)
.requestHandler(new EchoHandler())
.listen(port, result -> {
if (result.succeeded()) {
- startFuture.complete();
+ checkSuccess(startFuture, result);
} else {
startFuture.fail(result.cause());
}
});
- System.out.println("*** Starting EchoServerVertx on: " + port);
+ // HTTPS server
+ vertx.createHttpServer(httpsServerOptions)
+ .requestHandler(new EchoHandler())
+ .listen(port+1, result -> {
+ if (result.succeeded()) {
+ checkSuccess(startFuture, result);
+ } else {
+ startFuture.fail(result.cause());
+ }
+ });
+
+ log.info("*** Starting EchoServerVertx on HTTP: {0} HTTPS: {1}", port, port+1);
+ }
+
+ private void checkSuccess(Future<Void> startFuture, AsyncResult<HttpServer> result) {
+ toStart--;
+ if (toStart == 0) startFuture.complete();
+ }
+
+ private HttpServerOptions getHttpServerOptions() {
+ return getHttpServerOptions("http");
+ }
+
+ private HttpServerOptions getHttpsServerOptions() {
+ return getHttpServerOptions("https");
+ }
+
+ private HttpServerOptions getHttpServerOptions(String name) {
+ HttpServerOptions options = new HttpServerOptions();
+ HttpServerOptionsConverter.fromJson(config().getJsonObject(name, new JsonObject()), options);
+ if (JdkSSLEngineOptions.isAlpnAvailable()) {
+ options.setUseAlpn(true);
+ }
+ return options;
}
// Writes buffered chunks directly to the response and then calls #end.
@@ -130,9 +183,12 @@ public class EchoServerVertx extends AbstractVerticle {
@Override
public void handle(HttpServerRequest req) {
try {
+ req.exceptionHandler(ex -> {
+ handleError(req.response(), ex);
+ });
_handle(req);
- } catch (Exception e) {
- handleError(req.response(), e);
+ } catch (Exception ex) {
+ handleError(req.response(), ex);
}
}
@@ -200,8 +256,8 @@ public class EchoServerVertx extends AbstractVerticle {
});
}
- private void handleError(HttpServerResponse rep, Exception e) {
- e.printStackTrace();
+ private void handleError(HttpServerResponse rep, Throwable e) {
+ log.error(e);
if (!rep.ended()) {
rep.setStatusCode(500);
rep.end();
@@ -280,4 +336,36 @@ public class EchoServerVertx extends AbstractVerticle {
}
}
}
+
+ private JksOptions getKeystore() {
+ return getJksOptions("keystore", "jks/keystore.jks");
+ }
+
+ private JksOptions getTrustStore() {
+ return getJksOptions("trustStore", "jks/truststore.ts");
+ }
+
+ private JksOptions getJksOptions(String key, String defaultResource) {
+ JsonObject config = config()
+ .getJsonObject(key, new JsonObject());
+ JksOptions jksOptions = new JksOptions()
+ .setPassword(config.getString("password", "secret"))
+ .setValue(getResource(config.getString("resourceName", defaultResource)));
+ return jksOptions;
+ }
+
+ private Buffer getResource(String fPath) {
+ ClassLoader classLoader = getClass().getClassLoader();
+ File file = new File(classLoader.getResource(fPath).getFile());
+ Buffer buff;
+ try {
+ buff = Buffer.buffer(Files.readAllBytes(file.toPath()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return buff;
+ }
+
+
+
}

ADD
test/common/src/main/resources/jks/client.cer
test/common/src/main/resources/jks/client.cer
Binary files /dev/null and b/test/common/src/main/resources/jks/client.cer differ

ADD
test/common/src/main/resources/jks/keystore.jks
test/common/src/main/resources/jks/keystore.jks
Binary files /dev/null and b/test/common/src/main/resources/jks/keystore.jks differ

ADD
test/common/src/main/resources/jks/truststore.ts
test/common/src/main/resources/jks/truststore.ts
Binary files /dev/null and b/test/common/src/main/resources/jks/truststore.ts differ

feat(test-common): Add HTTPS and HTTP2 support to EchoServerVertx.