diff --git a/k8s/java/src/main/java/io/openkruise/agents/client/e2b/ConnectionConfig.java b/k8s/java/src/main/java/io/openkruise/agents/client/e2b/ConnectionConfig.java index 9fbf81d..5500ca9 100644 --- a/k8s/java/src/main/java/io/openkruise/agents/client/e2b/ConnectionConfig.java +++ b/k8s/java/src/main/java/io/openkruise/agents/client/e2b/ConnectionConfig.java @@ -46,6 +46,7 @@ public String getValue() { private int port; private int codeInterpreterPort; private Map headers; + private ProxyConfig proxyConfig; private volatile ApiClient apiClient; private volatile SandboxesApi sandboxesApi; @@ -77,6 +78,7 @@ private ConnectionConfig(ConnectionConfig config) { this.port = config.port; this.codeInterpreterPort = config.codeInterpreterPort; this.headers = new HashMap<>(config.headers); + this.proxyConfig = config.proxyConfig; this.urlBuilder = buildURLBuilder(); } @@ -134,6 +136,9 @@ public static RuntimeConfig toRuntimeConfig(ConnectionConfig connectionConfig, S .build(); builder.urlBuilder(urlBuilder); + + // Pass proxy configuration + builder.proxyConfig(connectionConfig.getProxyConfig()); return builder.build(); } @@ -159,6 +164,10 @@ public ApiClient getOrCreateApiClient() { synchronized (lock) { if (apiClient == null) { ApiClient client = new ApiClient(); + // Apply proxy configuration if enabled + if (proxyConfig != null) { + client.setHttpClient(proxyConfig.createHttpClient()); + } client.setBasePath(getAPIURL()); client.setConnectTimeout((int)requestTimeoutMs); client.setReadTimeout((int)requestTimeoutMs); @@ -214,6 +223,8 @@ private String getSchemeOrDefault() { public Map getHeaders() {return headers;} + public ProxyConfig getProxyConfig() {return proxyConfig;} + public static class Builder { private final ConnectionConfig config = new ConnectionConfig(); @@ -294,6 +305,11 @@ public Builder addHeader(String key, String value) { return this; } + public Builder proxyConfig(ProxyConfig proxyConfig) { + config.proxyConfig = proxyConfig; + return this; + } + public ConnectionConfig build() { config.urlBuilder = config.buildURLBuilder(); return new ConnectionConfig(config); diff --git a/k8s/java/src/main/java/io/openkruise/agents/client/e2b/ProxyConfig.java b/k8s/java/src/main/java/io/openkruise/agents/client/e2b/ProxyConfig.java new file mode 100644 index 0000000..a4c2c96 --- /dev/null +++ b/k8s/java/src/main/java/io/openkruise/agents/client/e2b/ProxyConfig.java @@ -0,0 +1,106 @@ +package io.openkruise.agents.client.e2b; + +import okhttp3.OkHttpClient; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.X509TrustManager; +import java.net.InetSocketAddress; +import java.net.Proxy; + +/** + * Proxy configuration for HTTP clients with SSL/TLS support. + * Customers should construct this class with their own proxy, SSLContext, TrustManager, and HostnameVerifier. + */ +public class ProxyConfig { + + private final Proxy proxy; + private final SSLContext sslContext; + private final X509TrustManager trustManager; + private final HostnameVerifier hostnameVerifier; + + private ProxyConfig(Builder builder) { + this.proxy = builder.proxy; + this.sslContext = builder.sslContext; + this.trustManager = builder.trustManager; + this.hostnameVerifier = builder.hostnameVerifier; + } + + public Proxy getProxy() { + return proxy; + } + + public SSLContext getSslContext() { + return sslContext; + } + + public X509TrustManager getTrustManager() { + return trustManager; + } + + public HostnameVerifier getHostnameVerifier() { + return hostnameVerifier; + } + + /** + * Applies proxy configuration to an OkHttpClient.Builder. + */ + public void applyTo(OkHttpClient.Builder builder) { + if (proxy != null) { + builder.proxy(proxy); + } + + if (sslContext != null && trustManager != null) { + builder.sslSocketFactory(sslContext.getSocketFactory(), trustManager); + } + + if (hostnameVerifier != null) { + builder.hostnameVerifier(hostnameVerifier); + } + } + + /** + * Creates an OkHttpClient with this proxy configuration. + */ + public OkHttpClient createHttpClient() { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + applyTo(builder); + return builder.build(); + } + + public static class Builder { + private Proxy proxy; + private SSLContext sslContext; + private X509TrustManager trustManager; + private HostnameVerifier hostnameVerifier; + + public Builder proxy(Proxy proxy) { + this.proxy = proxy; + return this; + } + + public Builder proxy(String host, int port) { + this.proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port)); + return this; + } + + public Builder sslContext(SSLContext sslContext) { + this.sslContext = sslContext; + return this; + } + + public Builder trustManager(X509TrustManager trustManager) { + this.trustManager = trustManager; + return this; + } + + public Builder hostnameVerifier(HostnameVerifier hostnameVerifier) { + this.hostnameVerifier = hostnameVerifier; + return this; + } + + public ProxyConfig build() { + return new ProxyConfig(this); + } + } +} diff --git a/k8s/java/src/main/java/io/openkruise/agents/client/e2b/README.md b/k8s/java/src/main/java/io/openkruise/agents/client/e2b/README.md index 4674233..d5ef3d4 100644 --- a/k8s/java/src/main/java/io/openkruise/agents/client/e2b/README.md +++ b/k8s/java/src/main/java/io/openkruise/agents/client/e2b/README.md @@ -26,6 +26,7 @@ try (sandbox) { ``` **Environment Variables Setup**: + ```bash export E2B_API_KEY="your-api-key" export E2B_DOMAIN="your.domain.com" @@ -474,6 +475,89 @@ Builder methods: | `E2B_API_KEY` | Default API Key | | `E2B_DOMAIN` | Default domain | +### Proxy Configuration (ProxyConfig) + +Supports accessing E2B services through an HTTP proxy, suitable for internal network environments or scenarios requiring +traffic forwarding. Also supports custom SSL/TLS configuration. + +#### Builder Methods + +| Method | Description | +|---------------------------------------|------------------------------------------| +| `.proxy(Proxy)` | Set Java `Proxy` object | +| `.proxy(String host, int port)` | Shortcut: create HTTP proxy by host/port | +| `.sslContext(SSLContext)` | Custom SSL context | +| `.trustManager(X509TrustManager)` | Custom certificate trust manager | +| `.hostnameVerifier(HostnameVerifier)` | Custom hostname verifier | + +#### Basic Usage + +```java +// 1. Build ProxyConfig +ProxyConfig proxyConfig = new ProxyConfig.Builder() + .proxy("proxy.example.com", 8080) + .build(); + +// 2. Set proxy in ConnectionConfig +ConnectionConfig config = new ConnectionConfig.Builder() + .apiKey("your-api-key") + .domain("your.domain.com") + .proxyConfig(proxyConfig) + .build(); + +SandboxApi api = new SandboxApi(config); +Sandbox sandbox = api.create("code-interpreter"); +``` + +#### Proxy Configuration with SSL/TLS + +For development/testing environments that need to trust self-signed certificates or skip certificate verification: + +```java +import javax.net.ssl.*; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; + +// 1. Create a TrustManager that trusts all certificates (for dev/test only) +TrustManager[] trustAll = new TrustManager[]{ + new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] c, String a) {} + @Override + public void checkServerTrusted(X509Certificate[] c, String a) {} + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + } +}; + +// 2. Initialize SSLContext +SSLContext sslCtx = SSLContext.getInstance("TLS"); +sslCtx.init(null, trustAll, new SecureRandom()); + +// 3. Build ProxyConfig +ProxyConfig proxyConfig = new ProxyConfig.Builder() + .proxy(new Proxy(Proxy.Type.HTTP, + new InetSocketAddress("proxy.example.com", 8080))) + .sslContext(sslCtx) + .trustManager((X509TrustManager) trustAll[0]) + .hostnameVerifier((hostname, session) -> true) + .build(); + +// 4. Set in ConnectionConfig +ConnectionConfig config = new ConnectionConfig.Builder() + .apiKey("your-api-key") + .domain("your.domain.com") + .proxyConfig(proxyConfig) + .build(); +``` + +> **Note**: Setting `proxyConfig(...)` automatically enables proxy. Proxy configuration applies to both control plane ( +> API calls) and data plane (Runtime connections). + --- ## 7. K8s Direct Connect Mode diff --git a/k8s/java/src/main/java/io/openkruise/agents/client/e2b/README_zh-CH.md b/k8s/java/src/main/java/io/openkruise/agents/client/e2b/README_zh-CH.md index d11efbe..5a5a72b 100644 --- a/k8s/java/src/main/java/io/openkruise/agents/client/e2b/README_zh-CH.md +++ b/k8s/java/src/main/java/io/openkruise/agents/client/e2b/README_zh-CH.md @@ -25,6 +25,7 @@ try (sandbox) { ``` **环境变量设置**: + ```bash export E2B_API_KEY="your-api-key" export E2B_DOMAIN="your.domain.com" @@ -465,6 +466,87 @@ Builder 构造时自动读取以下环境变量作为默认值,之后可通过 | `E2B_API_KEY` | 默认 API Key | | `E2B_DOMAIN` | 默认域名 | +### 代理配置(ProxyConfig) + +支持通过 HTTP 代理访问 E2B 服务,适用于内网环境或需要流量转发的场景。同时支持自定义 SSL/TLS 配置。 + +#### Builder 方法 + +| 方法 | 说明 | +|---------------------------------------|------------------------| +| `.proxy(Proxy)` | 设置 Java `Proxy` 对象 | +| `.proxy(String host, int port)` | 快捷方式:通过主机和端口创建 HTTP 代理 | +| `.sslContext(SSLContext)` | 自定义 SSL 上下文 | +| `.trustManager(X509TrustManager)` | 自定义证书信任管理器 | +| `.hostnameVerifier(HostnameVerifier)` | 自定义主机名验证器 | + +#### 基本用法 + +```java +// 1. 构建 ProxyConfig +ProxyConfig proxyConfig = new ProxyConfig.Builder() + .proxy("proxy.example.com", 8080) + .build(); + +// 2. 在 ConnectionConfig 中设置代理 +ConnectionConfig config = new ConnectionConfig.Builder() + .apiKey("your-api-key") + .domain("your.domain.com") + .proxyConfig(proxyConfig) + .build(); + +SandboxApi api = new SandboxApi(config); +Sandbox sandbox = api.create("code-interpreter"); +``` + +#### 带 SSL/TLS 的代理配置 + +适用于需要信任自签名证书或跳过证书验证的开发/测试环境: + +```java +import javax.net.ssl.*; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; + +// 1. 创建信任所有证书的 TrustManager(仅用于开发/测试环境) +TrustManager[] trustAll = new TrustManager[]{ + new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] c, String a) {} + @Override + public void checkServerTrusted(X509Certificate[] c, String a) {} + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + } +}; + +// 2. 初始化 SSLContext +SSLContext sslCtx = SSLContext.getInstance("TLS"); +sslCtx.init(null, trustAll, new SecureRandom()); + +// 3. 构建 ProxyConfig +ProxyConfig proxyConfig = new ProxyConfig.Builder() + .proxy(new Proxy(Proxy.Type.HTTP, + new InetSocketAddress("proxy.example.com", 8080))) + .sslContext(sslCtx) + .trustManager((X509TrustManager) trustAll[0]) + .hostnameVerifier((hostname, session) -> true) + .build(); + +// 4. 在 ConnectionConfig 中设置 +ConnectionConfig config = new ConnectionConfig.Builder() + .apiKey("your-api-key") + .domain("your.domain.com") + .proxyConfig(proxyConfig) + .build(); +``` + +> **注意**:设置 `proxyConfig(...)` 即自动启用代理。代理配置会同时应用于控制面(API 调用)和数据面(Runtime 连接)。 + --- ## 七、K8s 直连模式 diff --git a/k8s/java/src/main/java/io/openkruise/agents/client/runtime/RuntimeConfig.java b/k8s/java/src/main/java/io/openkruise/agents/client/runtime/RuntimeConfig.java index 6ccfc7b..005605b 100644 --- a/k8s/java/src/main/java/io/openkruise/agents/client/runtime/RuntimeConfig.java +++ b/k8s/java/src/main/java/io/openkruise/agents/client/runtime/RuntimeConfig.java @@ -3,6 +3,7 @@ import com.google.protobuf.Message; import com.google.protobuf.MessageOrBuilder; import com.google.protobuf.util.JsonFormat; +import io.openkruise.agents.client.e2b.ProxyConfig; import io.openkruise.agents.client.url.URLBuilder; import okhttp3.MediaType; import okhttp3.OkHttpClient; @@ -38,6 +39,7 @@ public class RuntimeConfig { private final URLBuilder urlBuilder; private final int sandboxPort; private final int codeInterpreterPort; + private final ProxyConfig proxyConfig; protected RuntimeConfig(Builder builder) { this.domain = builder.domain; @@ -51,6 +53,7 @@ protected RuntimeConfig(Builder builder) { this.urlBuilder = builder.urlBuilder; this.sandboxPort = builder.sandboxPort; this.codeInterpreterPort = builder.codeInterpreterPort; + this.proxyConfig = builder.proxyConfig; } /** @@ -138,11 +141,17 @@ public OkHttpClient getOrCreateHttpClient() { throw new IllegalStateException("RuntimeConfig has been shut down"); } if (sharedHttpClient == null) { - sharedHttpClient = new OkHttpClient.Builder() + OkHttpClient.Builder builder = new OkHttpClient.Builder() .connectTimeout(requestTimeoutMs, TimeUnit.MILLISECONDS) .readTimeout(requestTimeoutMs, TimeUnit.MILLISECONDS) - .writeTimeout(requestTimeoutMs, TimeUnit.MILLISECONDS) - .build(); + .writeTimeout(requestTimeoutMs, TimeUnit.MILLISECONDS); + + // Apply proxy configuration if enabled + if (proxyConfig != null) { + proxyConfig.applyTo(builder); + } + + sharedHttpClient = builder.build(); } } } @@ -159,11 +168,17 @@ public OkHttpClient getOrCreateStreamingHttpClient() { throw new IllegalStateException("RuntimeConfig has been shut down"); } if (sharedStreamingClient == null) { - sharedStreamingClient = new OkHttpClient.Builder() + OkHttpClient.Builder builder = new OkHttpClient.Builder() .connectTimeout(requestTimeoutMs, TimeUnit.MILLISECONDS) .readTimeout(0, TimeUnit.MILLISECONDS) - .writeTimeout(requestTimeoutMs, TimeUnit.MILLISECONDS) - .build(); + .writeTimeout(requestTimeoutMs, TimeUnit.MILLISECONDS); + + // Apply proxy configuration if enabled + if (proxyConfig != null) { + proxyConfig.applyTo(builder); + } + + sharedStreamingClient = builder.build(); } } } @@ -289,6 +304,10 @@ public URLBuilder getUrlBuilder() { return urlBuilder; } + public ProxyConfig getProxyConfig() { + return proxyConfig; + } + /** * Builder pattern, extensible by subclasses. */ @@ -304,6 +323,7 @@ public static class Builder { protected URLBuilder urlBuilder; protected int sandboxPort = DEFAULT_RUNTIME_PORT; protected int codeInterpreterPort = DEFAULT_CODE_INTERPRETER_PORT; + protected ProxyConfig proxyConfig; public Builder() {} @@ -370,6 +390,11 @@ public Builder codeInterpreterPort(int codeInterpreterPort) { return this; } + public Builder proxyConfig(ProxyConfig proxyConfig) { + this.proxyConfig = proxyConfig; + return this; + } + public RuntimeConfig build() { return new RuntimeConfig(this); }