Add Java integration tests for phantom proxy tracing#4
Merged
Conversation
Adds two new integration test suites that verify phantom's proxy backend captures traffic from JVM-based applications: 1. tests/proxy_springboot_integration.rs — tests a minimal Spring Boot CommandLineRunner app (phantom-springboot-client) that reads HTTP_PROXY (injected by phantom) and uses java.net.http.HttpClient to make 2 HTTP and 2 HTTPS requests. Verifies all 4 traces are captured with correct status codes, bodies, and required trace fields. 2. tests/proxy_java_clients_integration.rs — tests four major Java HTTP client libraries (JDK HttpClient, AsyncHttpClient, Jetty HttpClient, Apache HttpClient 5) in a single plain-Java CLI app. Each client adds an x-phantom-client header for trace identification. Verifies 8 traces (4 clients × 2 schemes). Both apps use a trust-all SSLContext for HTTPS MITM capture and are built with mvn package before the test runs. Tests skip gracefully when java or mvn are not on PATH. https://claude.ai/code/session_01E3FVEjny7BKfgUeAGTM955
Spring Boot adds unnecessary framework overhead. The java-http-clients integration test covers the same proxy-capture scenarios using four major Java HTTP client libraries (JDK HttpClient, AsyncHttpClient, Jetty HttpClient, Apache HttpClient 5) without the Spring Boot dependency. https://claude.ai/code/session_01E3FVEjny7BKfgUeAGTM955
- Use wagon transport for Maven 3.9+ so settings.xml proxy auth works - Skip mvn package if JAR already built (faster re-runs) - Fix Java compile errors: add ProxyServer import, remove setSslContext from AsyncHttpClient (use setUseInsecureTrustManager only), replace TrustAllStrategy.INSTANCE with lambda for HttpClient 5 compatibility https://claude.ai/code/session_01E3FVEjny7BKfgUeAGTM955
Instead of requiring the Java test app to read HTTP_PROXY and configure each HTTP client library explicitly, phantom now injects the proxy settings transparently via JAVA_TOOL_OPTIONS when the child command is a java/javaw executable. Changes: - src/main.rs: add is_java_command() detection; when spawning a Java process, append -Dhttp.proxyHost, -Dhttps.proxyHost, -Dhttp.proxyPort, -Dhttps.proxyPort and -Dhttp.nonProxyHosts= to JAVA_TOOL_OPTIONS so any JVM application is proxied without app-level changes - Client.java: remove proxyAddress() and all explicit proxy setup; remove AsyncHttpClient and Jetty (they bypass JVM ProxySelector); keep JDK HttpClient (uses ProxySelector.getDefault() automatically) and Apache HttpClient 5 with SystemDefaultRoutePlanner - pom.xml: remove async-http-client, jetty-client, slf4j-nop deps - proxy_java_clients_integration.rs: update to 2 clients × 2 schemes = 4 traces; update comment to reflect transparent tracing concept https://claude.ai/code/session_01E3FVEjny7BKfgUeAGTM955
- Introduce Phantom Java Agent to force global ProxySelector and bypass SSL verification (trust-all). - Automatically inject -javaagent via JAVA_TOOL_OPTIONS when spawning Java processes in Rust. - Extend Java integration tests to cover 5 major clients: JDK HttpClient, Apache HC 5, OkHttp, Netty, and Jetty. - Update documentation with Java usage instructions. - Update .gitignore to exclude Java build artifacts.
- Use include_bytes! to embed phantom-java-agent.jar at compile time. - Extract JAR to a temporary file at runtime when tracing Java processes. - Ensure the temporary JAR is cleaned up after the process exits using RAII. - This enables a single-binary distribution for both Node.js and Java observability.
- Add build.rs to automatically compile and package the Java Agent JAR. - Rerun build.rs only if the Java source code changes. - This ensures the embedded phantom-java-agent.jar is always up-to-date and included in the binary.
8ded14c to
bed9559
Compare
- crates/phantom-agent/src/lib.rs: rewrite two HTTP/2 frame-processing loops as while-let and collapse a nested if into the match guard, per clippy's own suggested fixes (while_let_loop, collapsible_match). This pre-existing code was clean under the toolchain previously cached locally but is flagged by CI's newer stable clippy. - build.rs: write an empty placeholder phantom-java-agent.jar when javac is not on PATH. src/main.rs embeds this file unconditionally via include_bytes!, so its absence broke compilation entirely in JDK-less environments (e.g. the Docker integration-test image), not just the -javaagent feature. Verified by building with a PATH that hides javac/jar. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EgPcomgY5nj8RuU8V1G82Y
epli2
pushed a commit
that referenced
this pull request
Jul 6, 2026
Analyze current implementation and open PRs (#2, #4), redefine phantom's concept as a local-first API development toolbox (observe / perturb / record-replay / spec-gen), and lay out a 5-phase roadmap (P0-P4) with per-task dependencies, implementation steps, acceptance criteria, and an LLM-agent working protocol. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EgPcomgY5nj8RuU8V1G82Y
epli2
pushed a commit
that referenced
this pull request
Jul 6, 2026
…(P1-6)
- tests/apps/python-app/client.py + tests/proxy_python_integration.rs: Python
3 stdlib (urllib.request) HTTP+HTTPS capture, verified working out of the
box via phantom's auto-injected HTTP_PROXY/HTTPS_PROXY + SSL_CERT_FILE.
- tests/apps/go-app/client.go + tests/proxy_go_integration.rs: Go net/http
HTTP capture, verified working — scoped to HTTP only after discovering two
real limitations while building this (documented, not silently worked
around):
1. Go's net/http.ProxyFromEnvironment unconditionally refuses to proxy
requests to "localhost" or any loopback IP, regardless of
HTTP_PROXY/HTTPS_PROXY/NO_PROXY — confirmed directly against go1.24.
Not a phantom bug; the test backend binds to a dynamically-discovered
non-loopback address so the request actually reaches the proxy.
2. phantom's MITM leaf certificates only ever carry a DNS-name SAN, never
an IP SAN, even for IP-literal CONNECT targets — so any client with
strict RFC 6125 IP-literal verification (Go's crypto/tls confirmed;
likely others) rejects the cert. This is a phantom/hudsucker gap
affecting IP-literal HTTPS targets for every language, not Go-specific;
tracked as future work rather than fixed here.
- docs/compatibility.md: new runtime support matrix (Node/curl/Python
verified; Go verified with the HTTP-only caveat; Java per PR #4; several
runtimes honestly marked untested) plus write-ups of both limitations
above with the exact repro. Linked from README and AGENTS.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EgPcomgY5nj8RuU8V1G82Y
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds comprehensive integration tests for phantom's proxy backend with Java applications, verifying non-invasive HTTP/HTTPS traffic capture without requiring application code changes.
Key Changes
Two new integration test suites:
proxy_springboot_integration.rs: Tests phantom's proxy tracing with a Spring Boot CommandLineRunner application that makes HTTP and HTTPS requests via JDK HttpClient, readingHTTP_PROXYautomatically set by phantomproxy_java_clients_integration.rs: Tests phantom's proxy with four major Java HTTP client libraries (JDK HttpClient, AsyncHttpClient, Jetty HttpClient, Apache HttpClient 5), verifying each client can be transparently tracedTest applications:
tests/apps/springboot-app/: Spring Boot application with CommandLineRunner that makes HTTP/HTTPS requests to mock backends, demonstrating proxy-aware configuration via environment variablestests/apps/java-http-clients/: Plain Java CLI application testing four different HTTP client libraries with proxy configuration, each adding anx-phantom-clientheader for trace identificationMock backend infrastructure:
/api/health,/api/users(GET), and/api/users(POST) endpointsTest verification:
Implementation Details
java(17+) andmvnon PATH; gracefully skip if unavailableHTTP_PROXYenv var), demonstrating non-invasive tracinghttps://claude.ai/code/session_01E3FVEjny7BKfgUeAGTM955