A lightweight HTTP/HTTPS proxy library with pluggable interceptors and full MITM HTTPS support.
- HTTP Proxy — Full HTTP/1.1 proxy
- HTTPS Interception — Man-in-the-Middle mode with on-the-fly certificate generation
- HTTPS Pass-through — Secure tunneling via CONNECT (no decryption)
- Pluggable Interceptors — Chain-of-responsibility for inspecting/modifying requests and responses
- Certificate Authority — Auto-generated CA with per-hostname server certificates (BouncyCastle)
HttpProxyproxy = newHttpProxy();
proxy.start(8080);
// Option 1: Configure a specific HttpClientHttpClientclient = HttpClient.newBuilder()
.proxy(proxy.asProxySelector())
.build();
// Option 2: Set as system default for all HttpClient instancesProxySelector.setDefault(proxy.asProxySelector());
HttpClientclient = HttpClient.newHttpClient(); // Uses system defaultHttpResponse<String> response = client.send(
HttpRequest.newBuilder().uri(URI.create("http://example.com")).build(),
HttpResponse.BodyHandlers.ofString());
proxy.stop();HttpProxyproxy = newHttpProxy();
// Log all requestsproxy.addInterceptor((request, chain) -> {
System.out.println(request.getMethod() + " " + request.getUri());
returnchain.proceed(request);
});
// Add a custom headerproxy.addInterceptor((request, chain) -> {
ProxyRequestmodified = request.withHeader("X-Proxy", "tproxy");
returnchain.proceed(modified);
});
proxy.start(8080);proxy.addInterceptor((request, chain) -> {
ProxyResponseresponse = chain.proceed(request);
// Rewrite response bodyStringbody = newString(response.getBody());
Stringmodified = body.replace("server", "proxy");
returnresponse.withBody(modified.getBytes());
});proxy.addInterceptor((request, chain) -> {
if (request.getUri().getPath().equals("/api/users")) {
returnnewProxyResponse(200,
Headers.of("Content-Type", "application/json"),
"{\"users\":[]}".getBytes());
}
returnchain.proceed(request);
});Enable MITM mode to decrypt, inspect, and modify HTTPS traffic:
HttpProxyproxy = newHttpProxy();
proxy.enableHttpsInterception();
// Interceptors now see decrypted HTTPS requestsproxy.addInterceptor((request, chain) -> {
System.out.println("HTTPS: " + request.getUri()); // visible!returnchain.proceed(request);
});
proxy.start(8080);On first run, the proxy generates a CA certificate (tproxy-ca.crt) and keystore (tproxy-ca.p12). Clients must trust this CA. For HttpClient:
CertificateFactorycf = CertificateFactory.getInstance("X.509");
CertificatecaCert;
try (FileInputStreamfis = newFileInputStream("tproxy-ca.crt")) {
caCert = cf.generateCertificate(fis);
}
KeyStoretrustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
trustStore.setCertificateEntry("tproxy-ca", caCert);
TrustManagerFactorytmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
SSLContextsslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
HttpClientclient = HttpClient.newBuilder()
.proxy(proxy.asProxySelector())
.sslContext(sslContext)
.build();Without MITM enabled (the default), HTTPS tunnels through encrypted. Interceptors cannot see the content:
HttpProxyproxy = newHttpProxy();
proxy.start(8080); // HTTPS passes through unmodified- Client sends
CONNECT example.com:443to the proxy InterceptingConnectHandler(extends Jetty'sConnectHandler) redirects the tunnel to a local SSL-terminating connectorCertificateGeneratingKeyManagerreads the SNI hostname from the TLS ClientHello and generates a certificate signed by the proxy's CA- After SSL termination, the decrypted HTTP request flows through the normal servlet handler and interceptor chain
- The proxy forwards the request to the real server using a trust-all
HttpClient
./mvnw compile # Compile
./mvnw test# Run tests (38 tests)
./mvnw package # Package JAR- Java 21+
- Maven 3.6+
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Security Warning: This tool performs man-in-the-middle HTTPS interception. Use only for educational and testing purposes in controlled environments where you have proper authorization.