diff --git a/pom.xml b/pom.xml
index 217a19c..d3f560f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,9 @@
21
21
+
UTF-8
+ eu.m724.Main
@@ -20,6 +22,71 @@
json
20250107
+
+
+ org.slf4j
+ slf4j-api
+ 2.0.16
+
+
+ org.slf4j
+ slf4j-simple
+ 2.0.16
+
+
+
+ org.jetbrains
+ annotations
+ 26.0.1
+ compile
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.4.2
+
+
+
+ true
+ ${exec.mainClass}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.6.0
+
+
+ package
+
+ shade
+
+
+ true
+ false
+ true
+
+
+ *:*
+
+ META-INF/*.SF
+ META-INF/*.DSA
+ META-INF/*.RSA
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/eu/m724/Main.java b/src/main/java/eu/m724/Main.java
index fac62e9..42da78c 100644
--- a/src/main/java/eu/m724/Main.java
+++ b/src/main/java/eu/m724/Main.java
@@ -4,6 +4,8 @@ import eu.m724.docker.DockerEngine;
import eu.m724.docker.exception.FailedRequestException;
import eu.m724.docker.proxy.TcpSocketProxy;
import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.StandardProtocolFamily;
@@ -11,29 +13,30 @@ import java.net.UnixDomainSocketAddress;
import java.util.concurrent.ExecutionException;
public class Main {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
+
public static void main(String[] args) throws IOException, InterruptedException {
var proxy = new TcpSocketProxy(StandardProtocolFamily.UNIX, UnixDomainSocketAddress.of("/var/run/docker.sock"));
proxy.start();
- System.out.println("Started");
- System.out.printf("Tested in %d ms %n", proxy.test() / 1000000);
+ LOGGER.info("Latency to remote: {} ms", proxy.test() / 1000000);
var engine = new DockerEngine(proxy.getURI());
engine.ping().join();
var info = engine.info().join();
- System.out.println("Docker runtime:");
- System.out.println("- " + info.getString("ID"));
- System.out.println("- " + info.getString("OSType") + " " + info.getString("Architecture"));
- System.out.println("- OS: " + info.getString("OperatingSystem") + " " + info.getString("OSVersion"));
- System.out.println("- Hostname: " + info.getString("Name"));
+ LOGGER.info("Docker runtime:");
+ LOGGER.info("- {}", info.getString("ID"));
+ LOGGER.info("- {}, {}", info.getString("OSType"), info.getString("Architecture"));
+ LOGGER.info("- OS: {} version {}", info.getString("OperatingSystem"), info.getString("OSVersion"));
+ LOGGER.info("- Hostname: {}", info.getString("Name"));
JSONObject containerInfo = null;
try {
containerInfo = engine.inspectContainer("dcdn_nginx").get();
} catch (ExecutionException e) {
if (e.getCause() instanceof FailedRequestException fre && fre.getResponse().statusCode() == 404) {
- System.out.println("Container doesn't exist");
+ LOGGER.info("Container doesn't exist");
} else {
throw new RuntimeException("Exception getting container info", e);
}
@@ -41,14 +44,14 @@ public class Main {
if (containerInfo != null) {
var mounts = containerInfo.getJSONArray("Mounts");
- System.out.printf("Detected %d mounts:%n", mounts.length());
+ LOGGER.debug("Detected {} mounts:", mounts.length());
for (int i=0; i %s %n", j.getString("Name"), j.getString("Source"), j.getString("Destination"));
+ LOGGER.debug("{} {} -> {}", j.getString("Name"), j.getString("Source"), j.getString("Destination"));
}
} else {
- System.out.println("Creating it");
+ LOGGER.info("Creating it");
var data = new JSONObject()
.put("Image", "nginx:1.27");
diff --git a/src/main/java/eu/m724/docker/DockerEngine.java b/src/main/java/eu/m724/docker/DockerEngine.java
index dc94dc3..f06a1bc 100644
--- a/src/main/java/eu/m724/docker/DockerEngine.java
+++ b/src/main/java/eu/m724/docker/DockerEngine.java
@@ -3,6 +3,8 @@ package eu.m724.docker;
import org.json.JSONObject;
import java.net.URI;
+import java.net.http.HttpClient;
+import java.time.Duration;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
@@ -12,7 +14,7 @@ public class DockerEngine {
public DockerEngine(URI socketUri) {
- this.dao = new DockerEngineDAO(socketUri);
+ this.dao = new DockerEngineDAO(socketUri, HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).connectTimeout(Duration.ofSeconds(30)).build());
}
public CompletableFuture ping() {
diff --git a/src/main/java/eu/m724/docker/DockerEngineDAO.java b/src/main/java/eu/m724/docker/DockerEngineDAO.java
index d3151b3..5c8a6db 100644
--- a/src/main/java/eu/m724/docker/DockerEngineDAO.java
+++ b/src/main/java/eu/m724/docker/DockerEngineDAO.java
@@ -1,31 +1,34 @@
package eu.m724.docker;
import eu.m724.docker.exception.FailedRequestException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.net.URI;
+import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
-import java.time.Duration;
+import java.nio.charset.StandardCharsets;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class DockerEngineDAO {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DockerEngineDAO.class);
+
private final URI socketUri;
private final HttpClient httpClient;
- DockerEngineDAO(URI socketUri) {
+ DockerEngineDAO(URI socketUri, HttpClient httpClient) {
this.socketUri = socketUri;
- this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).connectTimeout(Duration.ofSeconds(30)).build();
+ this.httpClient = httpClient;
}
- public void close() {
- httpClient.close();
- }
-
-
/**
* Create a GET request that expects a JSON from the server.
* A {@link FailedRequestException} is thrown by the future if a non-200 status code is returned.
@@ -172,19 +175,16 @@ public class DockerEngineDAO {
}
- private HttpRequest createRequest(String path) {
- return HttpRequest.newBuilder(socketUri.resolve(path)).build();
- }
+ private CompletableFuture commonRequest(@NotNull String path, @Nullable Map queryParams, @Nullable JSONObject data, @NotNull HttpResponse.BodyHandler bodyHandler) {
+ Objects.requireNonNull(path, "Request path cannot be null");
+ Objects.requireNonNull(bodyHandler, "Body handler cannot be null");
- private CompletableFuture commonRequest(String path, Map queryParams, JSONObject data, HttpResponse.BodyHandler bodyHandler) {
if (queryParams != null && !queryParams.isEmpty()) {
- path += '?';
- path += queryParams.entrySet().stream()
- .map(e -> e.getKey() + '=' + e.getValue())
- .collect(Collectors.joining("&"));
+ path += encodeQueryParams(queryParams);
}
- System.out.println(path);
+ LOGGER.debug("Calling request: {}", path);
+
var builder = HttpRequest.newBuilder(socketUri.resolve(path));
if (data != null) {
@@ -200,4 +200,12 @@ public class DockerEngineDAO {
return response.body();
});
}
+
+ private String encodeQueryParams(@NotNull Map params) {
+ return params.entrySet().stream()
+ .map(e -> URLEncoder.encode(e.getKey(), StandardCharsets.UTF_8) +
+ "=" +
+ URLEncoder.encode(String.valueOf(e.getValue()), StandardCharsets.UTF_8))
+ .collect(Collectors.joining("&", "?", ""));
+ }
}
diff --git a/src/main/java/eu/m724/docker/exception/FailedRequestException.java b/src/main/java/eu/m724/docker/exception/FailedRequestException.java
index 10a9635..1ba3522 100644
--- a/src/main/java/eu/m724/docker/exception/FailedRequestException.java
+++ b/src/main/java/eu/m724/docker/exception/FailedRequestException.java
@@ -12,7 +12,7 @@ public class FailedRequestException extends CompletionException {
@Override
public String getMessage() {
- return "Code: " + response.statusCode() + " | Body: " + response.body();
+ return "Request failed with status %d: %s".formatted(response.statusCode(), response.body());
}
public HttpResponse> getResponse() {
diff --git a/src/main/java/eu/m724/docker/proxy/ConnectionThread.java b/src/main/java/eu/m724/docker/proxy/ConnectionThread.java
index 958ef73..de94228 100644
--- a/src/main/java/eu/m724/docker/proxy/ConnectionThread.java
+++ b/src/main/java/eu/m724/docker/proxy/ConnectionThread.java
@@ -1,5 +1,8 @@
package eu.m724.docker.proxy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.IOException;
import java.net.Socket;
import java.nio.ByteBuffer;
@@ -13,6 +16,8 @@ public class ConnectionThread extends Thread {
private final RemoteSocketFactory remoteSocketFactory;
private final Socket clientSocket;
+ private final Logger LOGGER = LoggerFactory.getLogger(ConnectionThread.class);
+
ConnectionThread(ExecutorService executorService, RemoteSocketFactory remoteSocketFactory, Socket clientSocket) {
this.executorService = executorService;
this.remoteSocketFactory = remoteSocketFactory;
@@ -25,11 +30,11 @@ public class ConnectionThread extends Thread {
clientSocket;
var remoteSocket = remoteSocketFactory.newChannel()
) {
- System.out.println("connected");
+ LOGGER.debug("starting inner");
inner(remoteSocket);
- System.out.println("disconnected");
+ LOGGER.debug("inner ended");
} catch (IOException e) {
- System.err.println("Exception handling client: " + e.getMessage());
+ LOGGER.error("Exception handling client", e);
}
}
diff --git a/src/main/java/eu/m724/docker/proxy/ServerRunnable.java b/src/main/java/eu/m724/docker/proxy/ServerRunnable.java
index 98a402f..bd2d7ca 100644
--- a/src/main/java/eu/m724/docker/proxy/ServerRunnable.java
+++ b/src/main/java/eu/m724/docker/proxy/ServerRunnable.java
@@ -1,10 +1,15 @@
package eu.m724.docker.proxy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.ExecutorService;
public class ServerRunnable implements Runnable {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ServerRunnable.class);
+
private final ExecutorService executorService;
private final ServerSocket serverSocket;
private final RemoteSocketFactory remoteSocketFactory;
@@ -26,7 +31,7 @@ public class ServerRunnable implements Runnable {
} catch (IOException e) {
if (serverSocket.isClosed()) break;
- System.err.println("Exception handling client request: " + e.getMessage());
+ LOGGER.error("Exception handling client request", e);
}
}
}
diff --git a/src/main/java/eu/m724/docker/proxy/TcpSocketProxy.java b/src/main/java/eu/m724/docker/proxy/TcpSocketProxy.java
index 400d7b3..a6a980b 100644
--- a/src/main/java/eu/m724/docker/proxy/TcpSocketProxy.java
+++ b/src/main/java/eu/m724/docker/proxy/TcpSocketProxy.java
@@ -1,11 +1,16 @@
package eu.m724.docker.proxy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.IOException;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TcpSocketProxy implements AutoCloseable {
+ private static final Logger LOGGER = LoggerFactory.getLogger(TcpSocketProxy.class);
+
private final RemoteSocketFactory remoteSocketFactory;
private ServerSocket serverSocket;
@@ -28,7 +33,7 @@ public class TcpSocketProxy implements AutoCloseable {
this.executorService = Executors.newVirtualThreadPerTaskExecutor();
executorService.execute(new ServerRunnable(executorService, serverSocket, remoteSocketFactory));
- System.out.println("Proxy bound on " + getURI());
+ LOGGER.info("Proxy bound on {}", getURI());
}
public long test() throws IOException {