Zuul routing the requests through an external proxy server
Asked Answered
D

2

6

Our current project requirement is to to route some requests to third-party external api servers. For this we are using spring zuul based router service.

zuul:
  routes
    test:
      path: /test/**
      serviceId: test
      url: http://my.api.server.com
    test2:
      path: /test2/**
      serviceId: test2
      url: http://my.api.server.com // but through an external proxy

Now the requirement is that for some endpoints, the requests to the external api server has be routed through some external proxy server, not owned by us,

How to do this via a curl is:

curl <external_api_server>/api/v1/user -k \
  -x tntqyhnhjym.sandbox.verygoodproxy.com:8080 \
  -H "Content-type: application/json" \
  -d '{"card_number": "tok_sandbox_t8VSoovCuHA779eJGZhKvg", ... }'

-x <proxy> redirects the request through the given proxy. How to do this via spring-zuul server?

There is one lead, I have gotten? https://github.com/spring-cloud/spring-cloud-netflix/issues/2320. Not clean, in the sense that I would need to extendSimpleHostRoutingFilter of zuul

Dentalium answered 16/10, 2020 at 7:41 Comment(2)
Service serviceId: test2 is one of the microservice of yours and you want to forward the request of test2 to an external server Is it? If yes, we may create the filter of pre type to forward requests to the external server for the /test2/** endpoints, Let me know your thoughts on the sameLuana
@PatelRomil, test2 is one of my microservice, and I want to forward the request to my api server(not the external server), but the condition is that I want to route the request through a proxy server. see example hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/…Dentalium
P
4

Option 1 - Reverse Proxy Server ( that uses the proxy)

You could setup a reverse proxy - that is configured to go through the proxy. Your reverse proxy would be started with the parameters (either in e.g. java or nodejs) to use the external proxy. This reverse proxy would be a different process that would pass all requests through the proxy you want.

You could do it either through setting up a second zuul proxy application or through a nodejs reverse proxy (express or node-http-proxy).

Second zuul application (only for externals)

So if you used zuul, you would make a second application with the following:

   test2:
      path: /proxied-test2/**
      serviceId: test2
      url: http://my.api.server.com 

You would then start this server on the same server with the parameters of your proxy and on a specific port (something like e.g. 9200) so e.g.

-Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888

Original Application

In your original application, you would replace your route to now be the following.

zuul:
  routes
    test:
      path: /test/**
      serviceId: test
      url: http://my.api.server.com
    test2:
      path: /test2/**
      serviceId: test2
      url: http://localhost:9200/proxied-test2/

Option 2: Use a scriptable http proxy server

You could setup a proxy server and then setup some exceptions and rules about which requests should be routed through the proxy and which requests should work without the proxy.

The second step is to configure your application to use the local proxy server specified in step 1. For this you can use the the following command-line parameters:

-Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888

I have configured exclude lists for proxy servers in the past, but I never configured/scripted include lists. In your case, it would make more sense to have include lists so I would test scriptable/programmable proxy servers, e.g.:


Paginate answered 24/10, 2020 at 1:11 Comment(0)
P
1

I also spent hours looking for a solution for this issue. I found a way which is more flexible and easier than those described previously.

You can implement a custom ProxySelector and define different proxies for every route you want.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.*;
import java.net.Proxy.Type;
import java.util.ArrayList;
import java.util.List;

public class CustomProxySelector extends ProxySelector {
    ProxySelector defaultProxySelector = ProxySelector.getDefault();

    ArrayList<Proxy> noProxy = new ArrayList<>();
    ArrayList<Proxy> proxies = new ArrayList<>();

    public CustomProxySelector(String proxyHost, int proxyPort) {
        noProxy.add(Proxy.NO_PROXY);
        proxies.add(new Proxy(Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
    }

    //define your custom proxy selection here
    @Override
    public List<Proxy> select(URI uri) {
        if (uri.getHost().matches("external.address.com")) {
            return proxies;
        }
        if (defaultProxySelector != null) {
            return defaultProxySelector.select(uri);
        }
        return noProxy;
    }

    @Override
    public void connectFailed(URI arg0, SocketAddress arg1, IOException arg2) {
        //error handling
    }
}

Then add a bean of type CloseableHttpClient which overwrites the standard HttpClient of Zuul and configure it with your custom implementation of ProxySelector.

@Bean
@Primary
public CloseableHttpClient customHttpClientForZuulWithHttpProxyConfig(@Value("${your.proxy.host}") String proxyHost, @Value("${your.proxy.port}") int proxyPort) {
    SystemDefaultRoutePlanner routePlanner = new SystemDefaultRoutePlanner(new CustomProxySelector(proxyHost, proxyPort));
    return HttpClientBuilder.create().setRoutePlanner(routePlanner).build();
}

Please also take note that zuul is not longer supported by spring cloud. so the recommended way is to switch to spring gateway.

Poitiers answered 11/5, 2022 at 20:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.