- Proxy configuration
- Configure retries of calls and timeouts
- URLs configuration
- SSL configuration
- Instrumenation of OpenTelemetry
To set up proxy use BoxApiConnection.setProxy to set proxy address and BoxApiConnection.setProxyBasicAuthentication to set username and password required by proxy:
BoxAPIConnection api=new BoxAPIConnection("access_token");
Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress("proxy_url",8888));
// You can use any subclass of BoxAPIConnection
api.setProxy(proxy);
api.setProxyBasicAuthentication("proxyUsername", "proxyPassword");
Proxy username and password will be used only if provided SocketAddress
is an instance of
InetSocketAddress
. If you would like to use a custom SocketAddress
you can provide your own
okhttp3.Authenticator
using BoxApiConnection.setProxyAuthenticator(Authenticator)
By using BoxApiConnection.setProxyBasicAuthentication you can enable default proxy authenticator that handles only Basic authentication. But you can provide your own authenticator by using BoxApiConnection.setProxyAuthenticator(Authenticator).
To do that you will need to add a dependency to your project:
"com.squareup.okhttp3:okhttp:XXX"
Please match the version with what SDK is using by checking build.gradle
and looking for entry implementation "com.squareup.okhttp3:okhttp:"
.
Now you can add an authenticator. by calling
BoxAPIConnection api = new BoxAPIConnection("access_token");
Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress("proxy_url",8888));
api.setProxy(proxy);
api.setProxyAuthenticator((route, response) -> response
.request()
.newBuilder()
.addHeader("Proxy-Authorization", "My custom authenticator")
.build()
);
For example, you can add NTLM authorization. This is example NTLM authenticator that is using parts from Apache Http Client 5.
import okhttp3.Authenticator;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.Route;
import org.apache.hc.client5.http.impl.auth.NTLMEngineException;
public class NTLMAuthenticator implements Authenticator {
final NTLMEngineImpl engine = new NTLMEngineImpl();
private final String domain;
private final String username;
private final String password;
private final String ntlmMsg1;
public NTLMAuthenticator(String username, String password, String domain) {
this.domain = domain;
this.username = username;
this.password = password;
String localNtlmMsg1 = null;
try {
localNtlmMsg1 = engine.generateType1Msg(null, null);
} catch (Exception e) {
e.printStackTrace();
}
ntlmMsg1 = localNtlmMsg1;
}
@Override
public Request authenticate(Route route, Response response) {
if(response.code() == 407 && "Proxy authorization required".equals(response.message())) {
String ntlmChallenge = response.headers("Proxy-Authenticate")
.stream()
.filter(h -> h.startsWith("NTLM "))
.findFirst().orElse("");
if(ntlmChallenge.length() > 5) {
try {
String ntlmMsg3 = engine.generateType3Msg(username, password.toCharArray(), domain, "ok-http-example-ntlm", ntlmChallenge.substring(5));
return response.request().newBuilder().header("proxy-Authorization", "NTLM " + ntlmMsg3).build();
} catch (NTLMEngineException e) {
throw new RuntimeException(e);
}
}
return response.request().newBuilder().header("proxy-Authorization", "NTLM " + ntlmMsg1).build();
}
return response.request();
}
}
The NTLMEngineImpl
could be created by using Apache implementation that can be found
here.
You can add a dependency to org.apache.httpcomponents.client5:httpclient5:5.1.3
.
Copy the NTLMEngineImpl
class and add it to your source.
Now you can use custom NTML Authenticator in your BoxAPIConnection
:
BoxAPIConnection api = new BoxAPIConnection("access_token");
Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress("proxy_url",8888));
api.setProxy(proxy);
api.setProxyAuthenticator(new NTLMAuthenticator("some proxy username", "some proxy password", "proxy workgroup"));
SDK can retry failed calls when:
- failed writting request body
- when recieved HTTP response code:
- 429 - rate limit exceeded
- 5XX - internal server error
- 400 error with error that
exp
claim has expired. This usially means there is a clock skew.
SDK is using exponnetial strategy to calculate time between retries.
If response contains Retry-After
header its value will be used as a wait time between calls.
You can check details in com.box.sdk.BoxAPIRequest.send(com.box.sdk.ProgressListener)
method.
To configure how many times API will retry calls use BoxApiConnection.setMaxRetryAttempts:
// You can use any subclass of BoxAPIConnection
api.setMaxRetryAttempts(10);
default value for retry attempts is 5
.
To set up how log (in milliseconds) API waits to establish connection use BoxApiConnection.setConnectTimeout:
// You can use any subclass of BoxAPIConnection
int connectionTimeout = 100; // timeout in milliseconds
api.setConnectTimeout(connectionTimeout);
default value is 0
which mean API waits forever to establish connection.
To set up how log (in milliseconds) API waits to read data from connection use BoxApiConnection.setReadTimeout:
// You can use any subclass of BoxAPIConnection
int readTimeout = 100; // timeout in milliseconds
api.setReadTimeout(readTimeout);
default value is 0
which mean API waits forever to read data from connection.
The default base URL used for making API calls to Box can be changed by calling BoxAPIConnection#setBaseURL(String)
method on BoxApiConnection
. Default value is https://api.box.com/
.
BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN");
api.setBaseURL("https://example.com");
String baseUrl = api.getBaseURL(); // will produce "https://example.com/2.0/"
Setting Base URL changes the Token and Revoke URL as well:
BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN");
api.setBaseURL("https://example.com");
String baseUrl = api.getBaseURL(); // will produce "https://example.com/2.0/"
String tokenUrl = api.getRevokeURL(); // will produce "https://example.com/oauth2/revoke"
String revokeUrl = api.getTokenURL(); // will produce "https://example.com/oauth2/token"
The default URL used for uploads can be changed by calling BoxAPIConnection#setBaseUploadURL(String)
method on BoxApiConnection
.
Default value is https://upload.box.com/api/
.
BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN");
api.setBaseUploadURL("https://upload.example.com");
api.getBaseUploadURL(); // will produce "https://upload.example.com/2.0/"
The default base app URL can be changed by calling BoxAPIConnection#setBaseAppUrl()
method on BoxApiConnection
.
Default value is https://app.box.com.
BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN");
api.setBaseAppUrl("https://example.app.com");
api.getBaseAppUrl(); // will produce "https://app.example.com"
The default URL used for getting token can be changed by calling setTokenURL()
method on BoxApiConnection
.
Default value is https://api.box.com/oauth2/token. This method is deprecated. Use BoxAPIConnection#setBaseURL(String)
instead.
BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN");
api.setTokenURL("https://example.com/token");
If you use setTokenUrl
this URL will be used over the one coming from setBaseUrl
when doing authentication.
The default URL used for invalidating token can be changed by calling setRevokeURL()
method on BoxApiConnection
.
Default value is https://api.box.com/oauth2/revoke. This method is deprecated. Use BoxAPIConnection#setBaseURL(String)
instead.
BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN");
api.setRevokeURL("https://example.com/revoke");
If you use setRevokeUrl
this URL will be used over the one coming fromsetBaseUrl
when doing authentication.
You can override default settings used to verify SSL certificates. This can be used to allow using self-signed certificates. For example:
BoxAPIConnection api = new BoxAPIConnection(...);
// to allow self-signed certificates
X509TrustManager trustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
};
// to allow self-signed certificates created for localhost
HostnameVerifier hostnameVerifier = (hostname, session) -> true;
api.configureSslCertificatesValidation(trustManager, hostnameVerifier);
If you just need to provide trust manager use BoxAPIConnection.DEFAULT_HOSTNAME_VERIFIER
as a hostname verifier.
The same goes for hostname verifier. If you need just to provide it use
BoxAPIConnection.DEFAULT_TRUST_MANAGER
as a trust manager.
Example:
BoxAPIConnection api = new BoxAPIConnection(...);
X509TrustManager trustManager = ...
api.configureSslCertificatesValidation(trustManager, BoxAPIConnection.DEFAULT_HOSTNAME_VERIFIER);
OpenTelemetry is an observability framework and toolkit for creating and managing telemetry data, such as traces, metrics, and logs. The Box Java SDK can be instrumented with OpenTelemetry to collect telemetry data about the requests made by the SDK.
To start, add the opentelemetry-okhttp-3.0 dependency to your project.
Next, create a custom class that extends BoxAPIConnection and integrates telemetry in the overridden createNewCall
method.
Here's an example implementation:
public class BoxAPIConnectionWithTelemetry extends BoxAPIConnection {
private OkHttpTelemetry telemetry;
public BoxAPIConnectionWithTelemetry(String accessToken) {
super(accessToken);
}
/**
* Add required constructors
*/
public void setTelemetry(OpenTelemetry openTelemetry) {
this.telemetry = OkHttpTelemetry.builder(openTelemetry).build();
}
protected Call createNewCall(OkHttpClient httpClient, Request request) {
return this.telemetry.newCallFactory(httpClient).newCall(request);
}
}
Please note that you should not modify either httpClient
or request
parameters in the createNewCall method.
Altering these parameters can discard the BoxAPIConnection configuration and lead to unexpected behavior.