symphonyoss / symphony-java-client

Java client library for Symphony
Apache License 2.0
34 stars 37 forks source link

Timeout Exception on trying to authenticate - Proxy Support #15

Closed kaushikchaubal closed 8 years ago

kaushikchaubal commented 8 years ago

Hi,

As we try to use the java-client within a corporate proxy, we get the following exception:

javax.ws.rs.ProcessingException: java.net.ConnectException: Connection timed out: connect at org.glassfish.jersey.client.HttpUrlConnector.apply(HttpUrlConnector.java:229) at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:246) at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:667) at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:664) at org.glassfish.jersey.internal.Errors.process(Errors.java:315) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:228) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444) at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:664) at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:424) at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:333) at org.symphonyoss.symphony.authenticator.invoker.ApiClient.invokeAPI(ApiClient.java:619) at org.symphonyoss.symphony.authenticator.api.AuthenticationApi.v1AuthenticatePost(AuthenticationApi.java:71) at org.symphonyoss.symphony.clients.AuthorizationClient.authenticate(AuthorizationClient.java:69) at org.symphonyoss.com.symphonyoss_client.SymphonyService.authenticate(SymphonyService.java:37) at

Our suspicion is that we need to set proxies but there is no support for proxies as of now. Is there proxy support planned for this?

pmonks commented 8 years ago

I'm firing completely from the hip here, but have you tried setting Java's HTTP proxy global properties? This should be a quick & easy test to run, although depending on which HTTP client library the swagger-generated code uses, it might not work (not all Java HTTP client libraries respect these global properties).

kaushikchaubal commented 8 years ago

Yes - we did try the global proxy setting but it didn't work. Exploring other options on stackoverflow for now. I think it would be ideal if maybe the SymphonyBasicClient or the SymphonyClientFactory exposes this.

pmonks commented 8 years ago

I'll shut up now and let the experts ( @ftbb ) take over. 😉

HelenMRankin commented 8 years ago

After a little experimentation, we have found a way to set the proxy which doesn't require any code changes to SymphonyOSS:

1 . Create an HttpUrlConnectionProvider and change the ConnectionFactory, overriding the getConnection method:

HttpUrlConnectorProvider connectorProvider = new HttpUrlConnectorProvider();
HttpUrlConnectorProvider.ConnectionFactory connectionFactory = new HttpUrlConnectorProvider.ConnectionFactory() {
    @Override
    public HttpURLConnection getConnection(URL url) throws IOException {
        try {
            final HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) new URL(url.toExternalForm()).openConnection(proxy);
            return httpsUrlConnection;
        } catch (final IOException e) {
            LOG.error("Can't open connection to " + url, e);
            throw new RuntimeException("Can't open connection to " + url, e);
        }
    }
};
connectorProvider.connectionFactory(connectionFactory);

2 . Create a ClientConfig, setting the ConnectionProvider to the one you created. Build a new client using this config:

final ClientConfig clientConfig = new ClientConfig();
clientConfig.connectorProvider(connectorProvider);

Client client = ClientBuilder.newBuilder().withConfig(clientConfig).build();

3 . Create a new ApiClient for each the agent, authenticator and pod APIs, and set the underlying Http Client to the one you created. Make these the default clients for each configuration (I've just done this for the authenticator API below):

ApiClient defaultClient = new ApiClient();
defaultClient.setHttpClient(client);
org.symphonyoss.symphony.authenticator.invoker.Configuration.setDefaultApiClient(defaultClient);

Now when you try to connect, it should connect via proxy. When you create instances of various clients, e.g. AuthorizationClient or MessagesClient, it should use this configuration.

Using this method it is possible to completely configure the underlying HttpClient - for example, if you do not want to use a password for the trust store, you can build the client with a custom SSLContext.

ftbb commented 7 years ago

Update on this subject. commit 38d3a02240d3e8368a7c9edde7f01b4809c56a69

The latest snapshot supports custom Http Clients.

Specifically you can build and use your own custom javax.ws.rs.client.Client as the default base httpclient to a SymphonyClient instance.

This helps with things like proxies or having a single BOT connecting as multiple users (different certs).

Example: https://github.com/symphonyoss/symphony-java-client/blob/master/symphony-client-examples/src/main/java/org/symphonyoss/examples/multiclient/MultiClientExample.java

(Sorry this took so long!)

pmonks commented 7 years ago

@HelenMRankin would it make sense to add your example code above to CustomHttpClient, perhaps as an overloaded version of the getClient method?

ftbb commented 7 years ago

To make this easier...I just added the ability to submit a ClientConfig to the packaged CustomHttpClient class.

CustomHttpClient.getClient(String clientKeyStore, String clientKeyStorePass, String trustStore, String trustStorePass, ClientConfig clientConfig)

Frank