@@ -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.\n Trailer: " + 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}
0 commit comments