Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Helidon Webclient (4.0.10) is not routing the requests through proxy configured using Proxy Builder. #9022

Closed
shashikumarmh77 opened this issue Jul 22, 2024 · 7 comments
Assignees
Labels
4.x Version 4.x bug Something isn't working P2 webclient
Milestone

Comments

@shashikumarmh77
Copy link

Environment Details

  • Helidon Version: 4.0.10
  • Helidon SE or Helidon MP - Helidon SE
  • JDK version: 21
  • OS: Linux
  • Docker version (if applicable):

Problem Description

I am trying to configure MockServer as a proxy to facilitate testing of REST requests.
In the following simplified test case, http://echo.jsontest.com/1/one is invoked. The actual endpoint returns {"1": "one"} but MockServer configured as proxy should return mocked response of {"1": "ONE"}

@Test
    public void helidonClientWithProxySetUsingSystem() throws ExecutionException, InterruptedException, IOException {
        final String URL = "http://echo.jsontest.com/1/one";
        var builder = WebClient.builder().followRedirects(true).relativeUris(true)
                // set proxy address.
                .proxy(Proxy.builder().type(Proxy.ProxyType.HTTP).host("localhost").port(1026))
                .baseUri(URL);
        var webClient = builder.build();
        var webClientRequestBuilder = webClient.method(Method.GET);
        System.out.println("Invoking " + URL);
        try (HttpClientResponse response = webClientRequestBuilder.request()) {
            System.out.println("Response code with WebClient:" + response.status().code());
        }
    }

However, the execution results in below exception.

o.helidon.common.buffers.DataReader$InsufficientDataAvailableException
	at io.helidon.common.buffers.DataReader.pullData(DataReader.java:83)
    ...
	at io.helidon.webclient.http1.Http1StatusParser.readStatus(Http1StatusParser.java:48)
	at io.helidon.webclient.http1.Http1CallChainBase.readResponse(Http1CallChainBase.java:218)
	at io.helidon.webclient.http1.Http1CallEntityChain.doProceed(Http1CallEntityChain.java:66)
	at io.helidon.webclient.http1.Http1CallChainBase.proceed(Http1CallChainBase.java:149)
	at io.helidon.webclient.api.ClientRequestBase.invokeServices(ClientRequestBase.java:395)
	at io.helidon.webclient.http1.Http1ClientRequestImpl.invokeWithServices(Http1ClientRequestImpl.java:205)
	at io.helidon.webclient.http1.Http1ClientRequestImpl.invokeRequestWithEntity(Http1ClientRequestImpl.java:195)
	at io.helidon.webclient.http1.RedirectionProcessor.invokeWithFollowRedirects(RedirectionProcessor.java:49)
	at io.helidon.webclient.http1.RedirectionProcessor.invokeWithFollowRedirects(RedirectionProcessor.java:40)
    ...
	at io.helidon.webclient.api.ClientRequestBase.validateAndSubmit(ClientRequestBase.java:452)
	at io.helidon.webclient.api.ClientRequestBase.submit(ClientRequestBase.java:266)
	at io.helidon.webclient.api.HttpClientRequest.doSubmit(HttpClientRequest.java:79)
	at io.helidon.webclient.api.ClientRequestBase.validateAndSubmit(ClientRequestBase.java:452)
	at io.helidon.webclient.api.ClientRequestBase.request(ClientRequestBase.java:257)

Steps to reproduce

  1. Download the mockserver jar and start mockserver (test expects it at port 1026), see this page
  2. Register an expectation
    curl -X PUT "http://localhost:1026/mockserver/expectation" -H 'Content-Type: application/x-www-form-urlencoded' -d '{ "httpRequest": { "method": "GET", "path": "/1/one" }, "httpResponse": {"body": {"1": "ONE"}}}'
  3. Run above test which results in the above error.

Sample code:
ClientTest.txt

@klustria
Copy link
Member

Some observations to this issue:

  1. The behavior is the same for Helidon 3 Webclient.
  2. Proxying with curl to MockServer works. User also claims that jdk's httpURLConnection() also works.
  3. Proxying with Helidon Webclient works with mitmproxy but fails with MockServer. After inspecting the protocol exchange using Wireshark, it looks like MockServer does not respond to Connect which is what the Webclient uses to initiate proxy, while mitmproxy does.
  4. Curl does not use CONNECT to proxy when using http, but looks like it does for https. It seems to use the same method as the request, for example, it just uses GET, when the request is a GET.

@m0mus m0mus added bug Something isn't working P2 webclient 4.x Version 4.x labels Jul 22, 2024
@spericas
Copy link
Member

@jbescos
Copy link
Member

jbescos commented Jul 23, 2024

It works if we avoid the HTTP CONNECT when it is HTTP (not HTTPs). However, I think this is an issue in MockServer, because CONNECT is also necessary with HTTP when you use authentication. They should always respond to CONNECT.

I am going to open them one issue.

My reproducer for test:

@ServerTest
class HttpMockProxyTest {

    private static final int PROXY_PORT = 1080;
    private final WebClient webClient;
    private final int serverPort;
    private ClientAndServer mockServer;

    HttpMockProxyTest(WebServer server) {
        this.serverPort = server.port();
        this.webClient = WebClient.builder()
                .baseUri("http://localhost:" + serverPort)
                .proxy(Proxy.builder().host("localhost").port(PROXY_PORT).build())
                .build();
    }

    @SetUpRoute
    static void routing(HttpRouting.Builder router) {
        router.route(GET, "/get", Routes::get);
    }

    @BeforeEach
    public void before() {
        mockServer = startClientAndServer(PROXY_PORT);
        mockServer.when(request()).forward(forward().withScheme(Scheme.HTTP).withHost("localhost").withPort(serverPort)); 
    }

    @AfterEach
    public void after() {
        mockServer.stop();
    }

    @Test
    public void issue9022() {
        try (HttpClientResponse response = webClient.get("/get").request()) {
            assertThat(response.status(), is(Status.OK_200));
            String entity = response.entity().as(String.class);
            assertThat(entity, is("Hello"));
        }
    }

    private static class Routes {
        private static String get() {
            return "Hello";
        }
    }
}

jbescos added a commit to jbescos/helidon that referenced this issue Jul 23, 2024
…roxy configured using Proxy Builder. helidon-io#9022

Signed-off-by: Jorge Bescos Gascon <[email protected]>
@jbescos
Copy link
Member

jbescos commented Jul 23, 2024

I have created an issue there: mock-server/mockserver#1890

@shashikumarmh77
Copy link
Author

shashikumarmh77 commented Jul 23, 2024

@jbescos Thanks for filing a bug with mock server. Since curl and HttpURLConnection works is it possible to bypass the CONNECT used by helidon to connect to the proxy as done by curl and HttpUTLConnection (May be introducing a flag at builder level)

@jbescos
Copy link
Member

jbescos commented Jul 23, 2024

I created a PR in the way @shashikumarmh77 suggested.

jbescos added a commit to jbescos/helidon that referenced this issue Jul 23, 2024
…roxy configured using Proxy Builder. helidon-io#9022

Signed-off-by: Jorge Bescos Gascon <[email protected]>
jbescos added a commit to jbescos/helidon that referenced this issue Jul 23, 2024
…roxy configured using Proxy Builder. helidon-io#9022

Signed-off-by: Jorge Bescos Gascon <[email protected]>
jbescos added a commit to jbescos/helidon that referenced this issue Jul 23, 2024
…roxy configured using Proxy Builder. helidon-io#9022

Signed-off-by: Jorge Bescos Gascon <[email protected]>
jbescos added a commit to jbescos/helidon that referenced this issue Jul 24, 2024
…roxy configured using Proxy Builder. helidon-io#9022

Signed-off-by: Jorge Bescos Gascon <[email protected]>
@m0mus m0mus added this to the 4.1.0 milestone Jul 25, 2024
jbescos added a commit that referenced this issue Jul 31, 2024
…roxy configured using Proxy Builder. #9022 (#9023)

4.x: Helidon Webclient (4.0.10) is not routing the requests through proxy configured using Proxy Builder. #9022

Signed-off-by: Jorge Bescos Gascon <[email protected]>
@klustria
Copy link
Member

klustria commented Jul 31, 2024

Closing this issue as @jbescos has merged the resolution to this issue via PR #9023.

@m0mus m0mus added this to Backlog Aug 12, 2024
@m0mus m0mus moved this to Closed in Backlog Aug 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.x Version 4.x bug Something isn't working P2 webclient
Projects
Archived in project
Development

No branches or pull requests

5 participants