Skip to content

Commit c4dea8d

Browse files
committed
(feat) add configurable timeout
1 parent 7143098 commit c4dea8d

File tree

4 files changed

+95
-49
lines changed

4 files changed

+95
-49
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ String apiSecret = "YOUR API SECRET";
6969
OpenTok opentok = new OpenTok(apiKey, apiSecret)
7070
```
7171

72+
#### Additional Configurations
73+
`.requestTimeout(int)` - Change the default HTTP request timeout, default is 60 seconds.
74+
`.apiUrl(String)` - Change the domain that the SDK points to. Useful when needing to select a specific datacenter or point to a mock version of the API for testing.
75+
`.proxy(Proxy)` - Using a `Proxy` object, you can configure a proxy server that the http client should use when accessing the OpenTok URLs.
76+
77+
7278
And make sure you call `close` when you are done to prevent leaked file descriptors.
7379

7480
```java

src/main/java/com/opentok/OpenTok.java

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public String generateToken(String sessionId, TokenOptions tokenOptions) throws
134134
} catch (UnsupportedEncodingException e) {
135135
throw new InvalidArgumentException("Session ID was not valid");
136136
}
137-
if (!sessionIdParts.contains(Integer.toString(this.apiKey))) {
137+
if (!sessionIdParts.contains(Integer.toString(apiKey))) {
138138
throw new InvalidArgumentException("Session ID was not valid");
139139
}
140140

@@ -244,7 +244,7 @@ public String generateToken(String sessionId) throws OpenTokException {
244244
public Session createSession(SessionProperties properties) throws OpenTokException {
245245
final SessionProperties _properties = properties != null ? properties : new SessionProperties.Builder().build();
246246
final Map<String, Collection<String>> params = _properties.toMap();
247-
final String response = this.client.createSession(params);
247+
final String response = client.createSession(params);
248248

249249
try {
250250
CreatedSession[] sessions = createdSessionReader.readValue(response);
@@ -306,7 +306,7 @@ public void signal(String sessionId, SignalProperties props) throws OpenTokExcep
306306
throw new InvalidArgumentException("Session string null or empty");
307307
}
308308
try {
309-
this.client.signal(sessionId,null,props);
309+
client.signal(sessionId,null,props);
310310

311311
} catch (Exception e)
312312
{
@@ -321,7 +321,7 @@ public void signal(String sessionId, String connectionId, SignalProperties props
321321
throw new InvalidArgumentException("Session or Connection string null or empty");
322322
}
323323
try {
324-
this.client.signal(sessionId, connectionId, props);
324+
client.signal(sessionId, connectionId, props);
325325

326326
} catch (Exception e)
327327
{
@@ -336,7 +336,7 @@ public void signal(String sessionId, String connectionId, SignalProperties props
336336
* @return The {@link Archive} object.
337337
*/
338338
public Archive getArchive(String archiveId) throws OpenTokException {
339-
String archive = this.client.getArchive(archiveId);
339+
String archive = client.getArchive(archiveId);
340340
try {
341341
return archiveReader.readValue(archive);
342342
} catch (Exception e) {
@@ -401,7 +401,7 @@ public ArchiveList listArchives(int offset, int count) throws OpenTokException {
401401
* @return A List of {@link Archive} objects.
402402
*/
403403
public ArchiveList listArchives(String sessionId, int offset, int count) throws OpenTokException {
404-
String archives = this.client.getArchives(sessionId, offset, count);
404+
String archives = client.getArchives(sessionId, offset, count);
405405
try {
406406
return archiveListReader.readValue(archives);
407407
} catch (JsonProcessingException e) {
@@ -442,7 +442,7 @@ public Archive startArchive(String sessionId, ArchiveProperties properties) thro
442442
throw new InvalidArgumentException("The resolution cannot be specified for individual output mode.");
443443
}
444444
// TODO: do validation on sessionId and name
445-
String archive = this.client.startArchive(sessionId, properties);
445+
String archive = client.startArchive(sessionId, properties);
446446
try {
447447
return archiveReader.readValue(archive);
448448
} catch (Exception e) {
@@ -470,7 +470,7 @@ public Archive startArchive(String sessionId, String name) throws OpenTokExcepti
470470
*/
471471
public Archive stopArchive(String archiveId) throws OpenTokException {
472472

473-
String archive = this.client.stopArchive(archiveId);
473+
String archive = client.stopArchive(archiveId);
474474
try {
475475
return archiveReader.readValue(archive);
476476
} catch (Exception e) {
@@ -488,7 +488,7 @@ public Archive stopArchive(String archiveId) throws OpenTokException {
488488
* @param archiveId The archive ID of the archive you want to delete.
489489
*/
490490
public void deleteArchive(String archiveId) throws OpenTokException {
491-
this.client.deleteArchive(archiveId);
491+
client.deleteArchive(archiveId);
492492
}
493493
/**
494494
* Sets the layout type for a composed archive. For a description of layout types, see
@@ -503,7 +503,7 @@ public void setArchiveLayout(String archiveId, ArchiveProperties properties) thr
503503
if (StringUtils.isEmpty(archiveId) || properties == null) {
504504
throw new InvalidArgumentException("ArchiveId is not valid or properties are null");
505505
}
506-
this.client.setArchiveLayout(archiveId, properties);
506+
client.setArchiveLayout(archiveId, properties);
507507
}
508508
/**
509509
* Use this method to start a live streaming for an OpenTok session.
@@ -533,7 +533,7 @@ public Broadcast startBroadcast(String sessionId, BroadcastProperties properties
533533
throw new InvalidArgumentException("Session not valid or broadcast properties is null");
534534
}
535535

536-
String broadcast = this.client.startBroadcast(sessionId, properties);
536+
String broadcast = client.startBroadcast(sessionId, properties);
537537
try {
538538
return broadcastReader.readValue(
539539
broadcast);
@@ -557,7 +557,7 @@ public Broadcast stopBroadcast(String broadcastId) throws OpenTokException {
557557
if (StringUtils.isEmpty(broadcastId)) {
558558
throw new InvalidArgumentException("Broadcast id is null or empty");
559559
}
560-
String broadcast = this.client.stopBroadcast(broadcastId);
560+
String broadcast = client.stopBroadcast(broadcastId);
561561
try {
562562
return broadcastReader.readValue(broadcast);
563563
} catch (Exception e) {
@@ -575,7 +575,7 @@ public Broadcast getBroadcast(String broadcastId) throws OpenTokException {
575575
if(StringUtils.isEmpty(broadcastId)) {
576576
throw new InvalidArgumentException("Broadcast id is null or empty");
577577
}
578-
String stream = this.client.getBroadcast(broadcastId);
578+
String stream = client.getBroadcast(broadcastId);
579579
try {
580580
return broadcastReader.readValue(stream);
581581
} catch (Exception e) {
@@ -596,7 +596,7 @@ public void setBroadcastLayout(String broadcastId, BroadcastProperties propertie
596596
if (StringUtils.isEmpty(broadcastId) || properties == null) {
597597
throw new InvalidArgumentException("BroadcastId is not valid or properties are null");
598598
}
599-
this.client.setBroadcastLayout(broadcastId, properties);
599+
client.setBroadcastLayout(broadcastId, properties);
600600
}
601601
/**
602602
* Sets the layout class list for streams in a session. Layout classes are used in
@@ -619,7 +619,7 @@ public void setStreamLayouts(String sessionId, StreamListProperties properties)
619619
if (StringUtils.isEmpty(sessionId) || properties == null) {
620620
throw new InvalidArgumentException("SessionId is not valid or properties are null");
621621
}
622-
this.client.setStreamLayouts(sessionId, properties);
622+
client.setStreamLayouts(sessionId, properties);
623623
}
624624

625625
/**
@@ -635,7 +635,7 @@ public void forceDisconnect(String sessionId, String connectionId) throws OpenTo
635635
throw new InvalidArgumentException("Session or Connection string null or empty");
636636
}
637637
try {
638-
this.client.forceDisconnect(sessionId, connectionId);
638+
client.forceDisconnect(sessionId, connectionId);
639639

640640
} catch (Exception e)
641641
{
@@ -652,7 +652,7 @@ public void forceDisconnect(String sessionId, String connectionId) throws OpenTo
652652
* @return The {@link Stream} object.
653653
*/
654654
public Stream getStream(String sessionId, String streamId) throws OpenTokException {
655-
String stream = this.client.getStream(sessionId, streamId);
655+
String stream = client.getStream(sessionId, streamId);
656656
try {
657657
return streamReader.readValue(stream);
658658
} catch (Exception e) {
@@ -668,7 +668,7 @@ public Stream getStream(String sessionId, String streamId) throws OpenTokExcepti
668668
* @return The list of {@link Stream} objects.
669669
*/
670670
public StreamList listStreams(String sessionId) throws OpenTokException {
671-
String streams = this.client.listStreams(sessionId);
671+
String streams = client.listStreams(sessionId);
672672
try {
673673
return streamListReader.readValue(streams);
674674
} catch (JsonProcessingException e) {
@@ -690,7 +690,7 @@ public Sip dial(String sessionId, String token, SipProperties properties) throws
690690
if((StringUtils.isEmpty(sessionId) || StringUtils.isEmpty(token) || properties == null || StringUtils.isEmpty(properties.sipUri()))) {
691691
throw new InvalidArgumentException ("Session id or token is null or empty or sip properties is null or sip uri empty or null.");
692692
}
693-
String sip = this.client.sipDial(sessionId,token,properties);
693+
String sip = client.sipDial(sessionId,token,properties);
694694
try {
695695
return sipReader.readValue(sip);
696696
} catch (JsonProcessingException e) {
@@ -707,6 +707,7 @@ public static class Builder {
707707
private ProxyAuthScheme proxyAuthScheme;
708708
private String principal;
709709
private String password;
710+
private int requestTimeout;
710711

711712
public Builder(int apiKey, String apiSecret) {
712713
this.apiKey = apiKey;
@@ -722,6 +723,11 @@ public Builder proxy(Proxy proxy) {
722723
proxy(proxy, null, null, null);
723724
return this;
724725
}
726+
727+
public Builder requestTimeout(int requestTimeout) {
728+
this.requestTimeout = requestTimeout * 1000;
729+
return this;
730+
}
725731

726732
public Builder proxy(Proxy proxy, ProxyAuthScheme proxyAuthScheme, String principal, String password) {
727733
this.proxy = proxy;
@@ -734,18 +740,21 @@ public Builder proxy(Proxy proxy, ProxyAuthScheme proxyAuthScheme, String princi
734740
public OpenTok build() {
735741
HttpClient.Builder clientBuilder = new HttpClient.Builder(apiKey, apiSecret);
736742

737-
if (this.apiUrl != null) {
738-
clientBuilder.apiUrl(this.apiUrl);
743+
if (apiUrl != null) {
744+
clientBuilder.apiUrl(apiUrl);
745+
}
746+
if (proxy != null) {
747+
clientBuilder.proxy(proxy, proxyAuthScheme, principal, password);
739748
}
740-
if (this.proxy != null) {
741-
clientBuilder.proxy(this.proxy, proxyAuthScheme, principal, password);
749+
if(requestTimeout !=0){
750+
clientBuilder.requestTimeoutMS(requestTimeout);
742751
}
743752

744-
return new OpenTok(this.apiKey, this.apiSecret, clientBuilder.build());
753+
return new OpenTok(apiKey, apiSecret, clientBuilder.build());
745754
}
746755
}
747756

748757
public void close() {
749-
this.client.close();
758+
client.close();
750759
}
751760
}

src/main/java/com/opentok/util/HttpClient.java

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,7 @@
1414
import com.fasterxml.jackson.databind.node.ArrayNode;
1515
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
1616
import com.fasterxml.jackson.databind.node.ObjectNode;
17-
import com.opentok.ArchiveLayout;
18-
import com.opentok.ArchiveProperties;
19-
import com.opentok.BroadcastLayout;
20-
import com.opentok.BroadcastProperties;
21-
import com.opentok.RtmpProperties;
22-
import com.opentok.SignalProperties;
23-
import com.opentok.SipProperties;
24-
import com.opentok.StreamListProperties;
25-
import com.opentok.StreamProperties;
17+
import com.opentok.*;
2618
import com.opentok.constants.DefaultApiUrl;
2719
import com.opentok.constants.Version;
2820
import com.opentok.exception.InvalidArgumentException;
@@ -830,6 +822,7 @@ public static class Builder {
830822
private String password;
831823
private String apiUrl;
832824
private AsyncHttpClientConfig config;
825+
private int requestTimeoutMS;
833826

834827
public Builder(int apiKey, String apiSecret) {
835828
this.apiKey = apiKey;
@@ -854,19 +847,34 @@ public Builder proxy(Proxy proxy, ProxyAuthScheme proxyAuthScheme, String princi
854847
return this;
855848
}
856849

850+
/**
851+
* Specify a custom timeout value for HTTP requests when initalizing a new {@link OpenTok} object.
852+
*
853+
* @param requestTimeoutMS request timeout in milliseconds
854+
* @return Builder
855+
*/
856+
public Builder requestTimeoutMS(int requestTimeoutMS) {
857+
this.requestTimeoutMS = requestTimeoutMS;
858+
return this;
859+
}
860+
857861
public HttpClient build() {
858862
DefaultAsyncHttpClientConfig.Builder configBuilder = new DefaultAsyncHttpClientConfig.Builder()
859863
.setUserAgent("Opentok-Java-SDK/" + Version.VERSION + " JRE/" + System.getProperty("java.version"))
860-
.addRequestFilter(new TokenAuthRequestFilter(this.apiKey, this.apiSecret));
861-
if (this.apiUrl == null) {
862-
this.apiUrl=DefaultApiUrl.DEFAULT_API_URI;
864+
.addRequestFilter(new TokenAuthRequestFilter(apiKey, apiSecret));
865+
if (apiUrl == null) {
866+
apiUrl=DefaultApiUrl.DEFAULT_API_URI;
863867
}
864868

865-
if (this.proxy != null) {
866-
configBuilder.setProxyServer(createProxyServer(this.proxy, this.proxyAuthScheme, this.principal, this.password));
869+
if (proxy != null) {
870+
configBuilder.setProxyServer(createProxyServer(proxy, proxyAuthScheme, principal, password));
871+
}
872+
873+
if(requestTimeoutMS != 0){
874+
configBuilder.setRequestTimeout(requestTimeoutMS);
867875
}
868876

869-
this.config = configBuilder.build();
877+
config = configBuilder.build();
870878
// NOTE: not thread-safe, config could be modified by another thread here?
871879
HttpClient client = new HttpClient(this);
872880
return client;

src/test/java/com/opentok/test/OpenTokTest.java

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
import java.util.ArrayList;
5454
import java.util.Arrays;
5555
import java.util.Map;
56+
import java.util.concurrent.TimeoutException;
57+
5658
import com.fasterxml.jackson.databind.*;
5759
import com.fasterxml.jackson.databind.node.ObjectNode;
5860

@@ -75,11 +77,7 @@
7577
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
7678
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
7779
import static org.hamcrest.CoreMatchers.instanceOf;
78-
import static org.junit.Assert.assertEquals;
79-
import static org.junit.Assert.assertNotNull;
80-
import static org.junit.Assert.assertNull;
81-
import static org.junit.Assert.assertThat;
82-
import static org.junit.Assert.assertTrue;
80+
import static org.junit.Assert.*;
8381

8482
public class OpenTokTest {
8583
private final String SESSION_CREATE = "/session/create";
@@ -114,6 +112,31 @@ public void setUp() throws OpenTokException {
114112
}
115113
sdk = new OpenTok.Builder(apiKey, apiSecret).apiUrl(apiUrl).build();
116114
}
115+
116+
/**
117+
* Test that a request throws exception if request exceeds configured timeout
118+
*
119+
* @throws OpenTokException
120+
*/
121+
@Test
122+
public void testConfigureRequestTimeout() throws OpenTokException {
123+
assertThrows(RequestException.class, () ->{
124+
sdk = new OpenTok.Builder(apiKey, apiSecret).apiUrl(apiUrl).requestTimeout(6).build();
125+
126+
String sessionId = "SESSIONID";
127+
stubFor(post(urlEqualTo(SESSION_CREATE))
128+
.willReturn(aResponse()
129+
.withStatus(200)
130+
.withFixedDelay(7000)
131+
.withHeader("Content-Type", "application/json")
132+
.withBody("[{\"session_id\":\"" + sessionId + "\",\"project_id\":\"00000000\"," +
133+
"\"partner_id\":\"123456\"," +
134+
"\"create_dt\":\"Mon Mar 17 00:41:31 PDT 2014\"," +
135+
"\"media_server_url\":\"\"}]")));
136+
137+
Session session = sdk.createSession();
138+
});
139+
}
117140

118141
@Test
119142
public void testSignalAllConnections() throws OpenTokException {
@@ -695,7 +718,7 @@ public void testListArchives() throws OpenTokException {
695718
assertNotNull(archives);
696719
assertEquals(6, archives.size());
697720
assertEquals(60, archives.getTotalCount());
698-
assertThat(archives.get(0), instanceOf(Archive.class));
721+
assertTrue(archives.get(0) instanceof Archive);
699722
assertEquals("ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", archives.get(0).getId());
700723
verify(getRequestedFor(urlMatching(archivePath)));
701724
assertTrue(Helpers.verifyTokenAuth(apiKey, apiSecret,
@@ -733,7 +756,7 @@ public void testListArchivesWithOffSetCount() throws OpenTokException {
733756
assertNotNull(archives);
734757
assertEquals(1, archives.size());
735758
assertEquals(60, archives.getTotalCount());
736-
assertThat(archives.get(0), instanceOf(Archive.class));
759+
assertTrue(archives.get(0) instanceof Archive);
737760
assertEquals("ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", archives.get(0).getId());
738761

739762
verify(getRequestedFor(urlEqualTo(url)));
@@ -771,7 +794,7 @@ public void testListArchivesWithSessionIdOffSetCount() throws OpenTokException {
771794
assertNotNull(archives);
772795
assertEquals(1, archives.size());
773796
assertEquals(60, archives.getTotalCount());
774-
assertThat(archives.get(0), instanceOf(Archive.class));
797+
assertTrue(archives.get(0) instanceof Archive);
775798
assertEquals("ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", archives.get(0).getId());
776799
verify(getRequestedFor(urlEqualTo(url)));
777800
assertTrue(Helpers.verifyTokenAuth(apiKey, apiSecret,
@@ -873,7 +896,7 @@ public void testListArchivesWithSessionId() throws OpenTokException {
873896
assertNotNull(archives);
874897
assertEquals(6, archives.size());
875898
assertEquals(60, archives.getTotalCount());
876-
assertThat(archives.get(0), instanceOf(Archive.class));
899+
assertTrue(archives.get(0) instanceof Archive);
877900
assertEquals("ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", archives.get(0).getId());
878901
verify(getRequestedFor(urlEqualTo(url)));
879902
assertTrue(Helpers.verifyTokenAuth(apiKey, apiSecret,

0 commit comments

Comments
 (0)