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

Reactive Web Client - Using HTTP proxy implicitly creates a tunnel [SPR-17234] #21767

Closed
spring-issuemaster opened this issue Sep 1, 2018 · 4 comments
Assignees

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Sep 1, 2018

Ron Klein opened SPR-17234 and commented

Expected behavior

When I run a local proxy (port 7000), and use curl, the command looks like this:

curl "http://httpbin.org/status/200" -x localhost:7000

What happens, and this is the expected behavior, is that curl establishes a TCP connection to localhost:7000, and runs the HTTP request against the local proxy, rather than the target (httpbin).

Actual behavior

If I use the following code:

public static void main(String[] args) {
  ReactorClientHttpConnector connector = new ReactorClientHttpConnector(options -> {
    options.httpProxy(addressSpec -> addressSpec.address(InetSocketAddress.createUnresolved("localhost", 7000)));
  });
  WebClient webClient = WebClient.builder()
      .clientConnector(connector)
      .build();

  String url = "http://httpbin.org/status/200";
  Mono<ClientResponse> exchange = webClient.get().uri(URI.create(url)).exchange();
  ClientResponse response = exchange.block();
  System.out.println(response.statusCode().value());
}

 

 

then the http client would first execute a CONNECT command (method) against the local proxy, and then would execute the original HTTP request (GET) inside the TCP level channel/tunnel it created from the executed CONNECT method.
I would expect that the default behavior when using a HTTP proxy would be the same as the one provided by curl, demonstrated above.

Spring Boot Version:
2.0.4.RELEASE
OS:
Mac 10.13.6


No further details from SPR-17234

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Sep 4, 2018

Brian Clozel commented

I believe you're referring to the difference between SOCKS and HTTP proxies and how clients connect through them. Or maybe, curl is not issuing CONNECT requests for non-https requests, and Netty is. In Reactor Netty 0.7 and 0.8, as well as in all curl versions, the default proxy is HTTP, so I think we're talking about the second.

If you're interested in connecting to a SOCKS proxy, then you can use more advanced client options on Reactor Netty itself, like (this is the new Reactor Netty 0.8 API, but the 0.7 one is quite similar):

TcpClient tcpClient = TcpClient.create().proxy(options -> options.type(ProxyProvider.Proxy.HTTP));
		HttpClient client = HttpClient.from(tcpClient);

In the meantime, the behavior you're describing is linked to the proxy handler implementation is Netty itself, so you might take this up to StackOverflow to understand the difference here, or create a reactor netty issue if you're confident this is a bug.

 Thanks!

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Sep 6, 2018

Ron Klein commented

Brian Clozel, thank you for your reply.

For the record, even if I'm trying your suggested solution, like so:

 

public static void main(String[] args) {

  HttpClient httpClient = HttpClient.builder().options(httpOptions -> {
    httpOptions.proxy(proxyOptions -> proxyOptions
        .type(Proxy.HTTP)
        .address(InetSocketAddress.createUnresolved("localhost", 7000))
    );
  }).build();

  String url = "http://httpbin.org/get";

  HttpClientResponse response = httpClient.get(url).block();

  System.out.println(response == null ? "null" : response.status().code());
}

I still see the CONNECT scenario.

However, this indeed seems to be a Reactor-Netty issue.

Thanks again!

 

 

 

 

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Sep 6, 2018

Brian Clozel commented

Hi Ron Klein,

This might actually be something done by design in Netty client itself. Apparently it supports SOCKS and HTTP Tunneling, which is consistent with the CONNECT frame you're seeing. See this package-info and this proxy implementation.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Sep 6, 2018

Ron Klein commented

Converted this issue to a feature request in Netty project:

netty/netty#8269

 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.