Skip to content

Commit bca9d3e

Browse files
author
gjeanmart
committed
fix conflict with master (timeout #f6ea7ce)
2 parents 33fe68a + 4bbf10a commit bca9d3e

File tree

2 files changed

+59
-23
lines changed

2 files changed

+59
-23
lines changed

src/main/java/io/ipfs/api/IPFS.java

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ public class IPFS {
1818
public enum PinType {all, direct, indirect, recursive}
1919
public List<String> ObjectTemplates = Arrays.asList("unixfs-dir");
2020
public List<String> ObjectPatchTypes = Arrays.asList("add-link", "rm-link", "set-data", "append-data");
21+
private static final int DEFAULT_TIMEOUT = 0;
2122

2223
public final String host;
2324
public final int port;
2425
public final String protocol;
2526
private final String version;
27+
private int timeout = DEFAULT_TIMEOUT;
2628
public final Key key = new Key();
2729
public final Pin pin = new Pin();
2830
public final Repo repo = new Repo();
@@ -73,6 +75,17 @@ public IPFS(String host, int port, String version, boolean ssl) {
7375
throw new RuntimeException(e);
7476
}
7577
}
78+
79+
/**
80+
* Configure a HTTP client timeout
81+
* @param timeout (default 0: infinite timeout)
82+
* @return current IPFS object with configured timeout
83+
*/
84+
public IPFS timeout(int timeout) {
85+
if(timeout < 0) throw new IllegalArgumentException("timeout must be zero or positive");
86+
this.timeout = timeout;
87+
return this;
88+
}
7689

7790
public List<MerkleNode> add(NamedStreamable file) throws IOException {
7891
return add(file, false);
@@ -659,13 +672,11 @@ private void retrieveAndParseStream(String path, Consumer<Object> results, Consu
659672

660673
private byte[] retrieve(String path) throws IOException {
661674
URL target = new URL(protocol, host, port, version + path);
662-
return IPFS.get(target);
675+
return IPFS.get(target, timeout);
663676
}
664677

665-
private static byte[] get(URL target) throws IOException {
666-
HttpURLConnection conn = (HttpURLConnection) target.openConnection();
667-
conn.setRequestMethod("GET");
668-
conn.setRequestProperty("Content-Type", "application/json");
678+
private static byte[] get(URL target, int timeout) throws IOException {
679+
HttpURLConnection conn = configureConnection(target, "GET", timeout);
669680

670681
try {
671682
InputStream in = conn.getInputStream();
@@ -678,8 +689,12 @@ private static byte[] get(URL target) throws IOException {
678689
return resp.toByteArray();
679690
} catch (ConnectException e) {
680691
throw new RuntimeException("Couldn't connect to IPFS daemon at "+target+"\n Is IPFS running?");
692+
} catch (SocketTimeoutException e) {
693+
throw new RuntimeException(String.format("timeout (%d ms) has been exceeded", timeout));
681694
} catch (IOException e) {
682-
String err = new String(readFully(conn.getErrorStream()));
695+
String err = Optional.ofNullable(conn.getErrorStream())
696+
.map(s->new String(readFully(s)))
697+
.orElse(e.getMessage());
683698
throw new RuntimeException("IOException contacting IPFS daemon.\nTrailer: " + conn.getHeaderFields().get("Trailer") + " " + err, e);
684699
}
685700
}
@@ -725,28 +740,24 @@ private List<Object> getAndParseStream(String path) throws IOException {
725740

726741
private InputStream retrieveStream(String path) throws IOException {
727742
URL target = new URL(protocol, host, port, version + path);
728-
return IPFS.getStream(target);
743+
return IPFS.getStream(target, timeout);
729744
}
730745

731-
private static InputStream getStream(URL target) throws IOException {
732-
HttpURLConnection conn = (HttpURLConnection) target.openConnection();
733-
conn.setRequestMethod("GET");
734-
conn.setRequestProperty("Content-Type", "application/json");
746+
private static InputStream getStream(URL target, int timeout) throws IOException {
747+
HttpURLConnection conn = configureConnection(target, "GET", timeout);
735748
return conn.getInputStream();
736749
}
737750

738751
private Map postMap(String path, byte[] body, Map<String, String> headers) throws IOException {
739752
URL target = new URL(protocol, host, port, version + path);
740-
return (Map) JSONParser.parse(new String(post(target, body, headers)));
753+
return (Map) JSONParser.parse(new String(post(target, body, headers, timeout)));
741754
}
742755

743-
private static byte[] post(URL target, byte[] body, Map<String, String> headers) throws IOException {
744-
HttpURLConnection conn = (HttpURLConnection) target.openConnection();
756+
private static byte[] post(URL target, byte[] body, Map<String, String> headers, int timeout) throws IOException {
757+
HttpURLConnection conn = configureConnection(target, "POST", timeout);
745758
for (String key: headers.keySet())
746759
conn.setRequestProperty(key, headers.get(key));
747760
conn.setDoOutput(true);
748-
conn.setRequestMethod("POST");
749-
conn.setRequestProperty("Content-Type", "application/json");
750761
OutputStream out = conn.getOutputStream();
751762
out.write(body);
752763
out.flush();
@@ -756,16 +767,29 @@ private static byte[] post(URL target, byte[] body, Map<String, String> headers)
756767
return readFully(in);
757768
}
758769

759-
private static final byte[] readFully(InputStream in) throws IOException {
760-
ByteArrayOutputStream resp = new ByteArrayOutputStream();
761-
byte[] buf = new byte[4096];
762-
int r;
763-
while ((r=in.read(buf)) >= 0)
764-
resp.write(buf, 0, r);
765-
return resp.toByteArray();
770+
private static final byte[] readFully(InputStream in) {
771+
try {
772+
ByteArrayOutputStream resp = new ByteArrayOutputStream();
773+
byte[] buf = new byte[4096];
774+
int r;
775+
while ((r=in.read(buf)) >= 0)
776+
resp.write(buf, 0, r);
777+
return resp.toByteArray();
778+
779+
} catch(IOException ex) {
780+
throw new RuntimeException("Error reading InputStrean", ex);
781+
}
766782
}
767783

768784
private static boolean detectSSL(MultiAddress multiaddress) {
769785
return multiaddress.toString().contains("/https");
770786
}
787+
788+
private static HttpURLConnection configureConnection(URL target, String method, int timeout) throws IOException {
789+
HttpURLConnection conn = (HttpURLConnection) target.openConnection();
790+
conn.setRequestMethod(method);
791+
conn.setRequestProperty("Content-Type", "application/json");
792+
conn.setReadTimeout(timeout);
793+
return conn;
794+
}
771795
}

src/test/java/io/ipfs/api/APITest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,18 @@ public void toolsTest() throws IOException {
720720
Map commands = ipfs.commands();
721721
}
722722

723+
@Test(expected = RuntimeException.class)
724+
public void testTimeoutFail() throws IOException {
725+
IPFS ipfs = new IPFS(new MultiAddress("/ip4/127.0.0.1/tcp/5001")).timeout(1000);
726+
ipfs.cat(Multihash.fromBase58("QmYpbSXyiCTYCbyMpzrQNix72nBYB8WRv6i39JqRc8C1ry"));
727+
}
728+
729+
@Test
730+
public void testTimeoutOK() throws IOException {
731+
IPFS ipfs = new IPFS(new MultiAddress("/ip4/127.0.0.1/tcp/5001")).timeout(1000);
732+
ipfs.cat(Multihash.fromBase58("Qmaisz6NMhDB51cCvNWa1GMS7LU1pAxdF4Ld6Ft9kZEP2a"));
733+
}
734+
723735
// this api is disabled until deployment over IPFS is enabled
724736
public void updateTest() throws IOException {
725737
Object check = ipfs.update.check();

0 commit comments

Comments
 (0)