feat(#3235): add tests for proxy#4816
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughThis PR adds three Jetty dependencies to the integration test module and introduces a new integration test class that validates proxy functionality by spinning up a local proxy server and verifying HTTPS connectivity and EO project builds through it. Changes
Sequence Diagram(s)sequenceDiagram
participant Test as ProxyIT Test
participant Proxy as Local Jetty Proxy
participant Remote as Remote HTTPS Server
Test->>Proxy: 1. Start local proxy on free port
activate Proxy
Test->>Test: 2. Configure proxy settings
Test->>Proxy: 3. Send HTTPS request through proxy
activate Remote
Proxy->>Remote: 4. Forward request to target server
Remote-->>Proxy: 5. Return HTTPS response
deactivate Remote
Proxy-->>Test: 6. Return response to test
deactivate Proxy
Test->>Test: 7. Assert HTTP 200 & expected content
sequenceDiagram
participant Test as ProxyIT Test
participant Proxy as Local Jetty Proxy
participant Build as EO Build System
participant Remote as Package Repository
Test->>Proxy: 1. Start local proxy
activate Proxy
Test->>Build: 2. Create temp EO project
Test->>Build: 3. Configure proxy settings in build
Test->>Build: 4. Execute build stages (register, assemble, resolve, place)
activate Remote
Build->>Proxy: 5. Route artifact requests through proxy
Proxy->>Remote: 6. Fetch artifacts from repository
Remote-->>Proxy: 7. Return artifacts
deactivate Remote
Proxy-->>Build: 8. Deliver artifacts to build
deactivate Proxy
Build-->>Test: 9. Complete build
Test->>Test: 10. Assert BUILD SUCCESS in logs
Estimated Code Review Effort🎯 2 (Simple) | ⏱️ ~12 minutes Suggested Reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🚀 Performance AnalysisAll benchmarks are within the acceptable range. No critical degradation detected (threshold is 100%). Please refer to the detailed report for more information. Click to see the detailed report
|
There was a problem hiding this comment.
Pull request overview
This PR adds proxy testing capabilities to the eo-integration-tests module by introducing a new integration test class that verifies the eo-maven-plugin can work through a proxy server.
Changes:
- Adds ProxyIT.java with two tests: one verifying the proxy server setup works, and one testing that the Maven plugin can compile programs (though proxy usage is not yet enforced per the TODO)
- Adds Jetty dependencies (jetty-server, jetty-proxy, jetty-http) to support local proxy server setup for testing
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 20 comments.
| File | Description |
|---|---|
| eo-integration-tests/src/test/java/org/eolang/maven/ProxyIT.java | New integration test class with proxy server setup, verification tests, and helper methods for port allocation and test program generation |
| eo-integration-tests/pom.xml | Adds three Jetty dependencies (version 12.1.5) required for proxy server functionality in tests |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /** | ||
| * The proxy port. | ||
| */ | ||
| private int port; |
There was a problem hiding this comment.
This field has documentation but according to the project's coding guidelines, comments inside class bodies should be avoided as they negatively affect readability.
| MatcherAssert.assertThat( | ||
| "Proxy should return 200 OK for objectionary.com", | ||
| resp.statusCode(), | ||
| Matchers.equalTo(HttpStatus.OK_200) | ||
| ); | ||
| MatcherAssert.assertThat( | ||
| "Response body should contain objectionary.com", | ||
| resp.body(), | ||
| Matchers.allOf( | ||
| Matchers.containsString("objectionary"), | ||
| Matchers.containsString("sources") | ||
| ) | ||
| ); |
There was a problem hiding this comment.
This test contains two separate assertions (lines 79-83 and lines 84-91), but according to the project's coding guidelines, tests should contain only one assertion.
| .write(ProxyIT.program().getBytes(StandardCharsets.UTF_8)); | ||
| new AppendedPlugin(f).value() | ||
| .goals("register", "assemble", "resolve", "place"); | ||
| f.exec("package"); |
There was a problem hiding this comment.
According to the project's coding guidelines, blank lines inside method bodies should not be used as they reduce code readability.
| void stopProxy() throws Exception { | ||
| if (this.proxy != null && this.proxy.isStarted()) { | ||
| this.proxy.setStopTimeout(5000); | ||
| this.proxy.setStopAtShutdown(true); |
There was a problem hiding this comment.
According to the project's coding guidelines, blank lines inside method bodies should not be used as they reduce code readability.
| "+version 0.1.2", | ||
| "", | ||
| "# Prints Hello Proxy! to stdout.", | ||
| "[x] > main", |
There was a problem hiding this comment.
According to the project's coding guidelines, blank lines inside method bodies should not be used as they reduce code readability.
| /** | ||
| * Finds a free port. | ||
| * @return Free port number |
There was a problem hiding this comment.
According to the project's coding guidelines, comments inside method bodies should not be used as they negatively affect readability.
| "+package foo.x.y", | ||
| "+version 0.1.2", | ||
| "", | ||
| "# Prints Hello Proxy! to stdout.", |
There was a problem hiding this comment.
According to the project's coding guidelines, blank lines inside method bodies should not be used as they reduce code readability.
| /** | ||
| * The proxy server. | ||
| */ | ||
| private Server proxy; |
There was a problem hiding this comment.
This field has documentation but according to the project's coding guidelines, comments inside class bodies should be avoided as they negatively affect readability.
| if (this.proxy != null && this.proxy.isStarted()) { | ||
| this.proxy.setStopTimeout(5000); | ||
| this.proxy.setStopAtShutdown(true); | ||
| try { |
There was a problem hiding this comment.
According to the project's coding guidelines, blank lines inside method bodies should not be used as they reduce code readability.
| "+alias stdout org.eolang.io.stdout", | ||
| "+package foo.x.y", | ||
| "+version 0.1.2", | ||
| "", |
There was a problem hiding this comment.
According to the project's coding guidelines, blank lines inside method bodies should not be used as they reduce code readability.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@eo-integration-tests/pom.xml`:
- Around line 200-204: The jetty-http dependency is missing a test scope so it
will be included at compile time; update the pom dependency entry for artifactId
"jetty-http" to include a <scope>test</scope> element (matching the other Jetty
deps like jetty-server and jetty-proxy) so the dependency is only used during
tests.
In `@eo-integration-tests/src/test/java/org/eolang/maven/ProxyIT.java`:
- Around line 57-64: In setupProxy replace the two separate setHandler calls
that overwrite each other by composing the handlers so CONNECT tunneling is
applied alongside HTTP forwarding: create the ProxyHandler.Forward instance and
wrap or combine it with the ConnectHandler (e.g., new
ConnectHandler(forwardHandler) or use a HandlerList/HandlerCollection containing
forwardHandler and connectHandler) before calling this.proxy.setHandler;
reference the ProxyHandler.Forward and ConnectHandler used in the setupProxy
method so the server handles both forwarding and CONNECT.
🧹 Nitpick comments (3)
eo-integration-tests/src/test/java/org/eolang/maven/ProxyIT.java (2)
94-112: Test does not actually route Maven build through the proxy.As noted in the TODO (lines 36-42), the proxy is started but Maven is not configured to use it. The test currently validates that a build succeeds when a proxy exists on the system, not that the build uses the proxy. Consider renaming the test to reflect actual behavior until the TODO is addressed, e.g.,
checksThatBuildSucceedsWithProxyRunning.
114-125:setStopAtShutdown(true)is redundant when explicitly stopping.Since you're explicitly calling
stop()in@AfterEach, the shutdown hook registered bysetStopAtShutdown(true)serves no purpose and can be removed.♻️ Proposed simplification
`@AfterEach` void stopProxy() throws Exception { if (this.proxy != null && this.proxy.isStarted()) { this.proxy.setStopTimeout(5000); - this.proxy.setStopAtShutdown(true); try { this.proxy.stop(); } finally { this.proxy.destroy(); } } }eo-integration-tests/pom.xml (1)
187-199: Consider defining Jetty version as a property for consistency.Three Jetty dependencies (jetty-server, jetty-proxy, jetty-http) all use hardcoded version
12.1.5. Extracting this to a property would simplify future version updates.
| <dependency> | ||
| <groupId>org.eclipse.jetty</groupId> | ||
| <version>12.1.5</version> | ||
| <artifactId>jetty-http</artifactId> | ||
| </dependency> |
There was a problem hiding this comment.
Missing <scope>test</scope> for jetty-http dependency.
Unlike jetty-server and jetty-proxy, the jetty-http dependency is missing the test scope. Without it, the dependency defaults to compile scope and will be included in the production artifact.
🐛 Proposed fix
<dependency>
<groupId>org.eclipse.jetty</groupId>
<version>12.1.5</version>
<artifactId>jetty-http</artifactId>
+ <scope>test</scope>
</dependency>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <dependency> | |
| <groupId>org.eclipse.jetty</groupId> | |
| <version>12.1.5</version> | |
| <artifactId>jetty-http</artifactId> | |
| </dependency> | |
| <dependency> | |
| <groupId>org.eclipse.jetty</groupId> | |
| <version>12.1.5</version> | |
| <artifactId>jetty-http</artifactId> | |
| <scope>test</scope> | |
| </dependency> |
🤖 Prompt for AI Agents
In `@eo-integration-tests/pom.xml` around lines 200 - 204, The jetty-http
dependency is missing a test scope so it will be included at compile time;
update the pom dependency entry for artifactId "jetty-http" to include a
<scope>test</scope> element (matching the other Jetty deps like jetty-server and
jetty-proxy) so the dependency is only used during tests.
| @BeforeEach | ||
| void setupProxy() throws Exception { | ||
| this.port = ProxyIT.free(); | ||
| this.proxy = new Server(this.port); | ||
| this.proxy.setHandler(new ProxyHandler.Forward()); | ||
| this.proxy.setHandler(new ConnectHandler()); | ||
| this.proxy.start(); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Jetty 12 Server setHandler replace behavior multiple calls
💡 Result:
Short answer: calling Server.setHandler(...) replaces the server's single top-level handler — only the last handler you set is active. Server is a Handler.Wrapper/Singleton (one child), so multiple independent handlers must be composed (e.g. Handler.Sequence / Handler.Collection, ContextHandlerCollection, or wrap handlers with a wrapper like GzipHandler/GracefulHandler and set its child). Use add/setHandlers on a Handler.Collection (or build a tree via wrapper.setHandler(child)). [1][2][3]
Sources:
- Jetty programming guide (handler tree / ContextHandlerCollection examples). [1]
- Jetty Server javadoc (Server extends Handler.Wrapper / single-child semantics). [2]
- Handler.Collection API (use addHandler/replaceHandler/setHandlers for multiple children). [3]
🌐 Web query:
Jetty 12 ConnectHandler ProxyHandler.Forward composition wrap handler
💡 Result:
Yes — in Jetty 12 you compose ConnectHandler and ProxyHandler.Forward by wrapping the Forward proxy with a ConnectHandler (so CONNECT tunnels are handled) and setting that as the Server handler (or placing under a SecurityHandler if you need auth). Example:
- Handler tree for both plain HTTP and HTTPS (CONNECT): Server -> ConnectHandler -> ProxyHandler.Forward. See Jetty docs. [1]
Minimal Java example:
Server server = new Server();
server.addConnector(new ServerConnector(server));
// forward proxy (override as needed)
ProxyHandler.Forward forward = new ProxyHandler.Forward() {
`@Override`
public boolean handle(Request clientToProxyRequest, Response proxyToClientResponse, Callback proxyToClientCallback) {
String host = Request.getServerName(clientToProxyRequest);
if (host.endsWith(".blocked")) {
Response.writeError(clientToProxyRequest, proxyToClientResponse, proxyToClientCallback, HttpStatus.FORBIDDEN_403);
return true;
}
return super.handle(clientToProxyRequest, proxyToClientResponse, proxyToClientCallback);
}
};
// ConnectHandler wraps the forward proxy to support CONNECT/TLS tunnelling
ConnectHandler connect = new ConnectHandler(forward);
// Optionally configure connect white/black lists: connect.setWhiteList(...); connect.setBlackList(...);
server.setHandler(connect);
server.start();
Notes:
- If you only need plain HTTP (no CONNECT/tunnelling), you can set ProxyHandler.Forward directly as the Server handler. If you need both HTTP and HTTPS tunnelling, wrap the Forward with ConnectHandler as above. [1][2]
- Override newHttpClient()/configureHttpClient() on the Forward if you need custom HttpClient transport (HTTP/2, TLS, etc.). [1][3]
References:
- Jetty 12 Programming Guide — ConnectHandler and ProxyHandler usage. [1]
- ProxyHandler.Forward Javadoc. [2]
(If you want a complete copy-paste example with imports and HttpClient customisation, tell me and I’ll paste it.)
🌐 Web query:
Jetty 12 HTTPS CONNECT tunneling HTTP forwarding proxy setup
💡 Result:
Summary and quick setup (Jetty 12)
-
Jetty handles HTTPS tunneling (HTTP CONNECT) with ConnectHandler and plain HTTP forward proxying with ProxyHandler.Forward. ConnectHandler establishes TCP tunnels for CONNECT requests; ProxyHandler.Forward handles normal forwarded HTTP requests. [1]
-
If you run Jetty as a standalone distribution you can compose these handlers (and add SecurityHandler for proxy auth). Typical handler tree:
Server
└─ SecurityHandler (optional)
└─ ConnectHandler
└─ ProxyHandler.Forward
This allows CONNECT tunnels plus regular forward-proxy behavior and optional auth/whitelisting. [1] -
HttpClient (Jetty’s client library) supports configuring a forward proxy (including CONNECT behavior for HTTPS). Use org.eclipse.jetty.client.HttpClient when programmatically configuring clients. [2]
Minimal Java example (server-side handler wiring)
- Create a Server, instantiate ConnectHandler, instantiate ProxyHandler.Forward, set ProxyHandler.Forward as child of ConnectHandler, optionally wrap in a SecurityHandler (or override ConnectionHandler.handleAuthentication(...) for CONNECT auth), add to Server and start.
Example sketch:
Server server = new Server();
ConnectHandler connect = new ConnectHandler();
ProxyHandler.Forward forward = new ProxyHandler.Forward();
connect.setHandler(forward);
// optional: configure connect.setWhiteList(...)/setBlackList(...), add auth
server.setHandler(connect);
server.start();
(See Jetty docs for exact API names and configuration details.) [1][2]
Notes and pointers
- Use connect.setWhiteList(...) / setBlackList(...) to restrict allowed CONNECT targets; implement authentication via SecurityHandler or override ConnectionHandler.handleAuthentication(...). [1]
- If running behind TLS-terminating proxies or load balancers, consult Jetty’s docs about PROXY protocol / Forwarded headers and required modules. [3]
References
[1] Jetty 12 Server / ConnectHandler and ProxyHandler.Forward documentation.
[2] Jetty 12 HttpClient (forward proxy support).
[3] Jetty 12 operations guide — proxy/protocols (PROXY protocol, Forwarded header).
Second setHandler call overwrites the first, discarding ProxyHandler.Forward.
The ConnectHandler on line 62 replaces the ProxyHandler.Forward set on line 61. For a proxy supporting both HTTP forwarding and HTTPS CONNECT tunneling, handlers must be composed with ConnectHandler wrapping ProxyHandler.Forward.
🔧 Proposed fix
`@BeforeEach`
void setupProxy() throws Exception {
this.port = ProxyIT.free();
this.proxy = new Server(this.port);
- this.proxy.setHandler(new ProxyHandler.Forward());
- this.proxy.setHandler(new ConnectHandler());
+ final ConnectHandler connectHandler = new ConnectHandler();
+ connectHandler.setHandler(new ProxyHandler.Forward());
+ this.proxy.setHandler(connectHandler);
this.proxy.start();
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @BeforeEach | |
| void setupProxy() throws Exception { | |
| this.port = ProxyIT.free(); | |
| this.proxy = new Server(this.port); | |
| this.proxy.setHandler(new ProxyHandler.Forward()); | |
| this.proxy.setHandler(new ConnectHandler()); | |
| this.proxy.start(); | |
| } | |
| `@BeforeEach` | |
| void setupProxy() throws Exception { | |
| this.port = ProxyIT.free(); | |
| this.proxy = new Server(this.port); | |
| final ConnectHandler connectHandler = new ConnectHandler(); | |
| connectHandler.setHandler(new ProxyHandler.Forward()); | |
| this.proxy.setHandler(connectHandler); | |
| this.proxy.start(); | |
| } |
🤖 Prompt for AI Agents
In `@eo-integration-tests/src/test/java/org/eolang/maven/ProxyIT.java` around
lines 57 - 64, In setupProxy replace the two separate setHandler calls that
overwrite each other by composing the handlers so CONNECT tunneling is applied
alongside HTTP forwarding: create the ProxyHandler.Forward instance and wrap or
combine it with the ConnectHandler (e.g., new ConnectHandler(forwardHandler) or
use a HandlerList/HandlerCollection containing forwardHandler and
connectHandler) before calling this.proxy.setHandler; reference the
ProxyHandler.Forward and ConnectHandler used in the setupProxy method so the
server handles both forwarding and CONNECT.
|
@yegor256 would you mind having a look? |
|
@volodya-lombrozo Thanks for the contribution! You've earned +12 points for this: +16 as a basis, +0.05 points for each of 169 hits-of-code (capped at +16), -4 for exceeding 100 hits-of-code. Please keep them coming! Your running score is +171; don't forget to check your Zerocracy account too. |
This PR adds proxy tests to the
eo-integration-testsby introducing a new integration test and necessary Jetty dependencies.Related to #3235
Summary by CodeRabbit
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.