X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Futil%2FHttpUtils.java;h=5438d4e0e39aeb738b3ff11f2c3d19afe892cf48;hb=HEAD;hp=74f77a2ca72bc3c77e7e73777adeddb1d778809d;hpb=aada6c7d3345363bf8b889f960c6209e7bbe8c06;p=jalview.git diff --git a/src/jalview/util/HttpUtils.java b/src/jalview/util/HttpUtils.java index 74f77a2..a074a39 100644 --- a/src/jalview/util/HttpUtils.java +++ b/src/jalview/util/HttpUtils.java @@ -22,10 +22,44 @@ package jalview.util; import java.io.IOException; import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.ProtocolException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; +import java.net.URLConnection; + +import jalview.bin.Console; public class HttpUtils { + public final static String JALVIEWSCHEMEPREFIX = "jalview"; + + public static boolean isPlausibleUri(String s) + { + if (s == null) + { + return false; + } + if (startsWithHttpOrHttps(s) || isJalviewSchemeUri(s)) + { + return true; + } + try + { + URI u = new URI(s); + // allow file:/home/... as well as file:///home... as java copes + if (s.startsWith("file:/")) + { + return true; + } + } catch (URISyntaxException e) + { + return false; + } + return false; + } /** * Returns true if it is possible to open an input stream at the given URL, @@ -39,7 +73,7 @@ public class HttpUtils InputStream is = null; try { - is = new URL(url).openStream(); + is = HttpUtils.openStream(new URL(url)); if (is != null) { return true; @@ -69,4 +103,278 @@ public class HttpUtils return file.startsWith("http://") || file.startsWith("https://"); } + /** + * wrapper to get/post to a URL or check headers + * + * @param url + * @param ids + * @param readTimeout + * @return + * @throws IOException + * @throws ProtocolException + */ + public static boolean checkUrlAvailable(URL url, int readTimeout) + throws IOException, ProtocolException + { + // jalview.bin.Console.outPrintln(System.currentTimeMillis() + " " + url); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("HEAD"); + connection.setDoInput(true); + connection.setUseCaches(false); + connection.setConnectTimeout(300); + connection.setReadTimeout(readTimeout); + + // HttpURLConnection doesn't follow redirects from http to https. It should! + HttpURLConnection conn = followConnection(connection); + return conn.getResponseCode() == 200; + } + + /** + * wrapper to return a new HttpURLConnection to a new URL when there is a + * redirect from http to https, otherwise return the unused original + * HttpURLConnection + * + * @param HttpURLConnection + * conn0 + * @return HttpUrlConnection conn + */ + public static HttpURLConnection followConnection(HttpURLConnection conn0) + throws IOException + { + return followConnection(conn0, false); + } + + public static HttpURLConnection followConnection(HttpURLConnection conn0, + boolean followAnyway) throws IOException + { + URL url = conn0.getURL(); + // we are only checking for a redirect from http to https otherwise the java + // connection will follow when called (if not unset) + if (url == null) + { + return conn0; + } + if (!conn0.getInstanceFollowRedirects()) + { + return conn0; + } + if (!"http".equals(url.getProtocol()) && !followAnyway) + { + return conn0; + } + + // check the response code + HttpURLConnection checkConn = (HttpURLConnection) url.openConnection(); + httpURLConnectionCopyAttributes(conn0, checkConn); + + boolean redirectToHttps = false; + int response = checkConn.getResponseCode(); + checkConn.disconnect(); + if (response >= 300 && response < 400) + { + // we are only checking for a redirect from http to https + URL loc = new URL(conn0.getHeaderField("Location")); + if (loc != null && "https".equals(loc.getProtocol())) + { + redirectToHttps = true; + url = loc; + } + } + else if (followAnyway) + { + // checkConn might have followed a https->https redirect + url = checkConn.getURL(); + } + + if (!redirectToHttps && !followAnyway) + { + return conn0; + } + + // We want to return an HttpURLConnection to the new (probably https) URL + // that is unconnected in case further manipulation of the request is + // required. + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + httpURLConnectionCopyAttributes(conn0, conn); + return conn; + } + + private static void httpURLConnectionCopyAttributes( + HttpURLConnection conn0, HttpURLConnection conn1) + throws ProtocolException + { + conn1.setRequestMethod(conn0.getRequestMethod()); + conn1.setDoInput(conn0.getDoInput()); + conn1.setUseCaches(conn0.getUseCaches()); + conn1.setConnectTimeout(conn0.getConnectTimeout()); + conn1.setReadTimeout(conn0.getReadTimeout()); + conn1.setInstanceFollowRedirects(conn0.getInstanceFollowRedirects()); + } + + /** + * wrapper to follow a URL connection ALLOWING redirects from http to https + * + * @param URL + * url + * @return HttpUrlConnection conn + */ + public static URLConnection openConnection(URL url) throws IOException + { + return openConnection(url, false); + } + + public static URLConnection openConnection(URL url, boolean followAnyway) + throws IOException + { + if (url == null) + { + Console.debug("HttpUtils.openConnection(url) called with null url"); + return null; + } + Console.debug("HttpUtils.openConnection(url) called with url=" + + url.toString()); + URLConnection conn = null; + String protocol = url.getProtocol(); + if ("http".equals(protocol) || "https".equals(protocol)) + { + HttpURLConnection conn0 = (HttpURLConnection) url.openConnection(); + if (conn0 != null) + { + conn = HttpUtils.followConnection(conn0, followAnyway); + } + else + { + conn = conn0; + } + } + else + { + conn = url.openConnection(); + } + return conn; + } + + /** + * wrapper to follow a URL connection ALLOWING redirects from http to https + * and return the followed InputStream + * + * @param URL + * url + * @return HttpUrlConnection conn + */ + public static InputStream openStream(URL url) throws IOException + { + return openStream(url, false); + } + + public static InputStream openStream(URL url, boolean followAnyway) + throws IOException + { + if (url == null) + { + return null; + } + InputStream is = null; + String protocol = url.getProtocol(); + if ("http".equals(protocol) || "https".equals(protocol)) + { + HttpURLConnection conn = HttpUtils.followConnection( + (HttpURLConnection) url.openConnection(), followAnyway); + if (conn != null) + { + is = conn.getInputStream(); + } + } + else + { + is = url.openStream(); + } + return is; + } + + /** + * check if a jalview:// scheme URL is given + * + * @param String + * uri + * @return boolean + */ + public static boolean isJalviewSchemeUri(String jalviewUriString) + { + if (jalviewUriString == null) + { + return false; + } + URI jalviewUri; + try + { + jalviewUri = new URI(jalviewUriString); + } catch (URISyntaxException e) + { + return false; + } + String scheme = jalviewUri.getScheme(); + if (scheme == null || !scheme.startsWith(JALVIEWSCHEMEPREFIX)) + { + return false; + } + int jspl = JALVIEWSCHEMEPREFIX.length(); + return scheme.length() == jspl // jalview + || scheme.length() == jspl + 1 // jalviewX + || scheme.substring(jspl).equals("http") // jalviewhttp + || scheme.substring(jspl).equals("https"); // jalviewhttps + } + + /** + * convert a jalview scheme URI to its equivalent URL or path + * + * @param String + * uri + * @return String + */ + public static String equivalentJalviewUrl(String jalviewUriString) + { + if (!isJalviewSchemeUri(jalviewUriString)) + { + // not a jalviewUriString, hand it back + return jalviewUriString; + } + URI jalviewUri; + try + { + jalviewUri = new URI(jalviewUriString); + } catch (URISyntaxException e) + { + return null; + } + String scheme = jalviewUri.getScheme(); + String host = jalviewUri.getHost(); + if (host != null && host.length() > 0 || scheme + .substring(JALVIEWSCHEMEPREFIX.length()).startsWith("http")) + { + URI newUri; + try + { + newUri = new URI( + scheme.equals(JALVIEWSCHEMEPREFIX + "http") ? "http" + : "https", + jalviewUri.getUserInfo(), host, jalviewUri.getPort(), + jalviewUri.getPath(), jalviewUri.getQuery(), + jalviewUri.getFragment()); + // return a URL + return newUri.toURL().toString(); + } catch (URISyntaxException | MalformedURLException e) + { + ErrorLog.errPrintln("Trying to convert '" + jalviewUriString + + "' to URL failed"); + } + } + else + { + // return a file path (not a file URI) + return jalviewUri.getPath(); + } + return null; + } }