diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..0c234b0
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,19 @@
+FROM eclipse-temurin:17-jdk-jammy as builder
+
+RUN apt update && apt-get install maven -y
+
+WORKDIR /app
+
+RUN keytool -genkey -alias sitename -keyalg RSA -keystore keystore.jks -keysize 2048 -storepass 123456 -dname "CN=DD, OU=DD, O=DD, L=DD, S=DD, C=DD"
+
+COPY pom.xml ./
+COPY src/ ./src
+
+RUN mvn clean install
+
+FROM eclipse-temurin:17-jdk-jammy
+
+COPY --from=builder /app/target/httpbin-1.3.1-SNAPSHOT-jar-with-dependencies.jar httpbin.jar
+COPY --from=builder /app/keystore.jks /keystore.jks
+
+CMD ["java", "-jar", "httpbin.jar", "-keystore", "/keystore.jks" ]
diff --git a/pom.xml b/pom.xml
index aec0933..e845441 100644
--- a/pom.xml
+++ b/pom.xml
@@ -298,6 +298,11 @@
jetty-servlet
${jetty.version}
+
+ org.eclipse.jetty
+ jetty-util
+ ${jetty.version}
+
org.json
json
@@ -308,5 +313,10 @@
slf4j-api
2.0.6
+
+ commons-cli
+ commons-cli
+ 1.4
+
diff --git a/src/main/java/org/gaul/httpbin/HttpBin.java b/src/main/java/org/gaul/httpbin/HttpBin.java
index a00e382..c83f47d 100644
--- a/src/main/java/org/gaul/httpbin/HttpBin.java
+++ b/src/main/java/org/gaul/httpbin/HttpBin.java
@@ -17,13 +17,17 @@
package org.gaul.httpbin;
-import static java.util.Objects.requireNonNull;
-
-import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
/**
* Reimplementation of HttpBin https://httpbin.org/ suitable for offline unit
@@ -31,22 +35,54 @@
*/
public final class HttpBin {
private final Server server;
+ private final int mHTTPPort;
+ private final int mHTTPsPort;
- public HttpBin(URI endpoint) throws Exception {
- this(endpoint, new HttpBinHandler());
+ public HttpBin(String ip, int httpPort, int httpsPort, String keystore) throws Exception {
+ this(ip, httpPort, httpsPort, keystore, new HttpBinHandler());
}
- public HttpBin(URI endpoint, HttpBinHandler handler) throws Exception {
- requireNonNull(endpoint);
+ public HttpBin(String ip, int httpPort, int httpsPort, String keystore, HttpBinHandler handler) throws Exception {
server = new Server();
HttpConnectionFactory httpConnectionFactory =
new HttpConnectionFactory();
- ServerConnector connector = new ServerConnector(server,
+
+ mHTTPPort = httpPort;
+ mHTTPsPort = httpsPort;
+ List connectors = new ArrayList();
+ if (httpPort != 0) {
+ ServerConnector connector = new ServerConnector(server,
httpConnectionFactory);
- connector.setHost(endpoint.getHost());
- connector.setPort(endpoint.getPort());
- server.addConnector(connector);
+ connector.setHost(ip);
+ connector.setPort(httpPort);
+ connectors.add(connector);
+ }
+
+ if (httpsPort != 0) {
+ HttpConfiguration https = new HttpConfiguration();
+ SecureRequestCustomizer src = new SecureRequestCustomizer();
+ src.setSniHostCheck(false);
+ https.addCustomizer(src);
+ SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
+ sslContextFactory.setKeyStorePath(keystore);
+ sslContextFactory.setKeyStorePassword("123456");
+ sslContextFactory.setKeyManagerPassword("123456");
+
+ ServerConnector sslConnector = new ServerConnector(server,
+ new SslConnectionFactory(sslContextFactory, "http/1.1"),
+ new HttpConnectionFactory(https));
+ sslConnector.setHost(ip);
+ sslConnector.setPort(httpsPort);
+ connectors.add(sslConnector);
+ }
+
+ if (connectors.size() == 0) {
+ throw new Exception("At least one of ports must be set");
+ }
+ Connector[] customs = new Connector[connectors.size()];
+ connectors.toArray(customs);
+ server.setConnectors(customs);
server.setHandler(handler);
}
@@ -58,7 +94,11 @@ public void stop() throws Exception {
server.stop();
}
- public int getPort() {
- return ((ServerConnector) server.getConnectors()[0]).getLocalPort();
+ public int getHTTPPort() {
+ return mHTTPPort;
+ }
+
+ public int getHTTPsPort() {
+ return mHTTPsPort;
}
}
diff --git a/src/main/java/org/gaul/httpbin/Main.java b/src/main/java/org/gaul/httpbin/Main.java
index 8649c17..3420baa 100644
--- a/src/main/java/org/gaul/httpbin/Main.java
+++ b/src/main/java/org/gaul/httpbin/Main.java
@@ -17,7 +17,13 @@
package org.gaul.httpbin;
-import java.net.URI;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
public final class Main {
private Main() {
@@ -25,10 +31,40 @@ private Main() {
}
public static void main(String[] args) throws Exception {
- // TODO: configurable
- URI httpBinEndpoint = URI.create("http://127.0.0.1:8080");
+ Options options = new Options();
+ options.addOption(Option.builder("p")
+ .longOpt("port")
+ .hasArg()
+ .desc("http port")
+ .build());
+ options.addOption(Option.builder("s")
+ .longOpt("tls-port")
+ .hasArg()
+ .desc("https port")
+ .build());
+ options.addOption(Option.builder("ip")
+ .hasArg()
+ .desc("ip to listen on")
+ .build());
+ options.addOption(Option.builder("keystore")
+ .hasArg()
+ .required()
+ .build());
+ CommandLineParser parser = new DefaultParser();
+ try {
+ CommandLine cmd = parser.parse(options, args);
+ int httpPort = Integer.parseInt(cmd.getOptionValue("port", "8080"));
+ int httpsPort = Integer.parseInt(cmd.getOptionValue("tls-port", "8443"));
+ String ip = cmd.getOptionValue("ip", "0.0.0.0");
+ String keystore = cmd.getOptionValue("keystore");
- HttpBin httpBin = new HttpBin(httpBinEndpoint);
- httpBin.start();
+ HttpBin httpBin = new HttpBin(ip, httpPort, httpsPort, keystore);
+ httpBin.start();
+ } catch (ParseException e) {
+ System.err.println("Error parsing command line options: " + e.getMessage());
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("myapp", options);
+ System.exit(1);
+ }
}
}
diff --git a/src/test/java/org/gaul/httpbin/HttpBinTest.java b/src/test/java/org/gaul/httpbin/HttpBinTest.java
index 60c7831..d92d93d 100644
--- a/src/test/java/org/gaul/httpbin/HttpBinTest.java
+++ b/src/test/java/org/gaul/httpbin/HttpBinTest.java
@@ -43,13 +43,13 @@ public final class HttpBinTest {
@Before
public void setUp() throws Exception {
- httpBin = new HttpBin(httpBinEndpoint);
+ httpBin = new HttpBin("127.0.0.1", 8001, 0, "");
httpBin.start();
// reset endpoint to handle zero port
httpBinEndpoint = new URI(httpBinEndpoint.getScheme(),
httpBinEndpoint.getUserInfo(), httpBinEndpoint.getHost(),
- httpBin.getPort(), httpBinEndpoint.getPath(),
+ httpBin.getHTTPPort(), httpBinEndpoint.getPath(),
httpBinEndpoint.getQuery(), httpBinEndpoint.getFragment());
logger.debug("HttpBin listening on {}", httpBinEndpoint);