Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,16 @@ By default both the Java and Android clients use an `ExecutorService` to perform

Note that once you've shut down the publish executor for a given client, there is no way to restart or replace that executor. You will need to build a new client.

### Using an HTTP proxy

The KeenClient supports HTTP proxies via the `setProxy(String proxyHost, int proxyPort)` and `setProxy(Proxy proxy)` methods of a `KeenClient` instance. Simply use one of those methods after building a client like so:

```java
KeenClient client = new JavaKeenClientBuilder().build();
client.setProxy("secureproxy.example.com", 2570);
// now use the client object as you normally would
```

## Working with the Source

### Using IntelliJ IDEA or Android Studio
Expand Down
33 changes: 32 additions & 1 deletion core/src/main/java/io/keen/client/java/KeenClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
Expand Down Expand Up @@ -585,6 +587,34 @@ public boolean isActive() {
return isActive;
}

/**
* Sets an HTTP proxy server configuration for this client.
*
* @param proxyHost The proxy hostname or IP address.
* @param proxyPort The proxy port number.
*/
public void setProxy(String proxyHost, int proxyPort) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason not to have a setProxy(Proxy proxy) method instead? I guess it would be OK to have both, but I think some dependency injection here would help with testing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, does mutation of the proxy instance variable need to be synchronized? I don't think so but it's worth thinking through a little.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll add a direct setProxy(Proxy proxy) method, if only for testing (the String + int version seems more developer friendly). With that, I'll remove clearProxy as that will be redundant for setProxy(null).

I did consider synchronization and I'm pretty sure it doesn't need to be. Clearly, if proxy is being mutated and used (by sending events) on multiple threads, there will be race conditions, but synchronized mutators don't solve that (blocks synchronized around the client in the app's code could). Since proxy is passed to the Request constructor and is then final, the only possible synchronization issue is avoided: line 47 and 48 of UrlConnectionHttpHandler.

this.proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
}

/**
* Sets an HTTP proxy server configuration for this client.
*
* @param proxy The Proxy object to set.
*/
public void setProxy(Proxy proxy) {
this.proxy = proxy;
}

/**
* Gets the client Proxy.
*
* @return the proxy.
*/
public Proxy getProxy() {
return proxy;
}

///// PROTECTED ABSTRACT BUILDER IMPLEMENTATION /////

/**
Expand Down Expand Up @@ -983,6 +1013,7 @@ private enum ClientSingleton {
private String baseUrl;
private GlobalPropertiesEvaluator globalPropertiesEvaluator;
private Map<String, Object> globalProperties;
private Proxy proxy;

///// PRIVATE METHODS /////

Expand Down Expand Up @@ -1195,7 +1226,7 @@ public void writeTo(OutputStream out) throws IOException {

// Send the request.
String writeKey = project.getWriteKey();
Request request = new Request(url, "POST", writeKey, source);
Request request = new Request(url, "POST", writeKey, source, proxy);
Response response = httpHandler.execute(request);

// If logging is enabled, log the response.
Expand Down
9 changes: 8 additions & 1 deletion core/src/main/java/io/keen/client/java/http/Request.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.keen.client.java.http;

import java.net.Proxy;
import java.net.URL;

/**
Expand All @@ -16,14 +17,20 @@ public final class Request {
public final String method;
public final String authorization;
public final OutputSource body;
public final Proxy proxy;

///// PUBLIC CONSTRUCTORS /////

public Request(URL url, String method, String authorization, OutputSource body) {
this(url, method, authorization, body, null);
}

public Request(URL url, String method, String authorization, OutputSource body, Proxy proxy) {
this.url = url;
this.method = method;
this.authorization = authorization;
this.body = body;
this.proxy = proxy;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ public Response execute(Request request) throws IOException {
* @throws IOException If there is an error opening the connection.
*/
protected HttpURLConnection openConnection(Request request) throws IOException {
HttpURLConnection result = (HttpURLConnection) request.url.openConnection();
HttpURLConnection result;
if (request.proxy != null) {
result = (HttpURLConnection) request.url.openConnection(request.proxy);
} else {
result = (HttpURLConnection) request.url.openConnection();
}
result.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);
result.setReadTimeout(DEFAULT_READ_TIMEOUT);
return result;
Expand Down
12 changes: 12 additions & 0 deletions core/src/test/java/io/keen/client/java/KeenClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -596,4 +596,16 @@ public void onFailure(Exception e) {
}
}

@Test
public void testProxy() throws Exception {
KeenClient testClient = new TestKeenClientBuilder().build();

testClient.setProxy("1.2.3.4", 1234);
assertNotNull(testClient.getProxy());
assertEquals("/1.2.3.4:1234", testClient.getProxy().address().toString());

testClient.setProxy(null);
assertNull(testClient.getProxy());
}

}