Clover icon

Coverage Report

  1. Project Clover database Mon Nov 11 2024 17:27:16 GMT
  2. Package jalview.util

File HttpUtils.java

 

Coverage histogram

../../img/srcFileCovDistChart5.png
43% of files have more coverage

Code metrics

46
112
13
1
380
268
52
0.46
8.62
13
4

Classes

Class Line # Actions
HttpUtils 33 112 52
0.485380148.5%
 

Contributing tests

This file is covered by 124 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.util;
22   
23    import java.io.IOException;
24    import java.io.InputStream;
25    import java.net.HttpURLConnection;
26    import java.net.MalformedURLException;
27    import java.net.ProtocolException;
28    import java.net.URI;
29    import java.net.URISyntaxException;
30    import java.net.URL;
31    import java.net.URLConnection;
32   
 
33    public class HttpUtils
34    {
35    public final static String JALVIEWSCHEMEPREFIX = "jalview";
36   
 
37  176 toggle public static boolean isPlausibleUri(String s)
38    {
39  176 if (s == null)
40    {
41  0 return false;
42    }
43  176 if (startsWithHttpOrHttps(s) || isJalviewSchemeUri(s))
44    {
45  0 return true;
46    }
47  176 try
48    {
49  176 URI u = new URI(s);
50    // allow file:/home/... as well as file:///home... as java copes
51  176 if (s.startsWith("file:/"))
52    {
53  0 return true;
54    }
55    } catch (URISyntaxException e)
56    {
57  0 return false;
58    }
59  176 return false;
60    }
61   
62    /**
63    * Returns true if it is possible to open an input stream at the given URL,
64    * else false. The input stream is closed.
65    *
66    * @param url
67    * @return
68    */
 
69  0 toggle public static boolean isValidUrl(String url)
70    {
71  0 InputStream is = null;
72  0 try
73    {
74  0 is = HttpUtils.openStream(new URL(url));
75  0 if (is != null)
76    {
77  0 return true;
78    }
79    } catch (IOException x)
80    {
81    // MalformedURLException, FileNotFoundException
82  0 return false;
83    } finally
84    {
85  0 if (is != null)
86    {
87  0 try
88    {
89  0 is.close();
90    } catch (IOException e)
91    {
92    // ignore
93    }
94    }
95    }
96  0 return false;
97    }
98   
 
99  274 toggle public static boolean startsWithHttpOrHttps(String file)
100    {
101  274 return file.startsWith("http://") || file.startsWith("https://");
102    }
103   
104    /**
105    * wrapper to get/post to a URL or check headers
106    *
107    * @param url
108    * @param ids
109    * @param readTimeout
110    * @return
111    * @throws IOException
112    * @throws ProtocolException
113    */
 
114  0 toggle public static boolean checkUrlAvailable(URL url, int readTimeout)
115    throws IOException, ProtocolException
116    {
117    // jalview.bin.Console.outPrintln(System.currentTimeMillis() + " " + url);
118   
119  0 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
120  0 connection.setRequestMethod("HEAD");
121  0 connection.setDoInput(true);
122  0 connection.setUseCaches(false);
123  0 connection.setConnectTimeout(300);
124  0 connection.setReadTimeout(readTimeout);
125   
126    // HttpURLConnection doesn't follow redirects from http to https. It should!
127  0 HttpURLConnection conn = followConnection(connection);
128  0 return conn.getResponseCode() == 200;
129    }
130   
131    /**
132    * wrapper to return a new HttpURLConnection to a new URL when there is a
133    * redirect from http to https, otherwise return the unused original
134    * HttpURLConnection
135    *
136    * @param HttpURLConnection
137    * conn0
138    * @return HttpUrlConnection conn
139    */
 
140  0 toggle public static HttpURLConnection followConnection(HttpURLConnection conn0)
141    throws IOException
142    {
143  0 return followConnection(conn0, false);
144    }
145   
 
146  373 toggle public static HttpURLConnection followConnection(HttpURLConnection conn0,
147    boolean followAnyway) throws IOException
148    {
149  373 URL url = conn0.getURL();
150    // we are only checking for a redirect from http to https otherwise the java
151    // connection will follow when called (if not unset)
152  373 if (url == null)
153    {
154  0 return conn0;
155    }
156  373 if (!conn0.getInstanceFollowRedirects())
157    {
158  0 return conn0;
159    }
160  373 if (!"http".equals(url.getProtocol()) && !followAnyway)
161    {
162  308 return conn0;
163    }
164   
165    // check the response code
166  65 HttpURLConnection checkConn = (HttpURLConnection) url.openConnection();
167  65 httpURLConnectionCopyAttributes(conn0, checkConn);
168   
169  65 boolean redirectToHttps = false;
170  65 int response = checkConn.getResponseCode();
171  65 checkConn.disconnect();
172  65 if (response >= 300 && response < 400)
173    {
174    // we are only checking for a redirect from http to https
175  0 URL loc = new URL(conn0.getHeaderField("Location"));
176  0 if (loc != null && "https".equals(loc.getProtocol()))
177    {
178  0 redirectToHttps = true;
179  0 url = loc;
180    }
181    }
182  65 else if (followAnyway)
183    {
184    // checkConn might have followed a https->https redirect
185  0 url = checkConn.getURL();
186    }
187   
188  65 if (!redirectToHttps && !followAnyway)
189    {
190  65 return conn0;
191    }
192   
193    // We want to return an HttpURLConnection to the new (probably https) URL
194    // that is unconnected in case further manipulation of the request is
195    // required.
196  0 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
197  0 httpURLConnectionCopyAttributes(conn0, conn);
198  0 return conn;
199    }
200   
 
201  65 toggle private static void httpURLConnectionCopyAttributes(
202    HttpURLConnection conn0, HttpURLConnection conn1)
203    throws ProtocolException
204    {
205  65 conn1.setRequestMethod(conn0.getRequestMethod());
206  65 conn1.setDoInput(conn0.getDoInput());
207  65 conn1.setUseCaches(conn0.getUseCaches());
208  65 conn1.setConnectTimeout(conn0.getConnectTimeout());
209  65 conn1.setReadTimeout(conn0.getReadTimeout());
210  65 conn1.setInstanceFollowRedirects(conn0.getInstanceFollowRedirects());
211    }
212   
213    /**
214    * wrapper to follow a URL connection ALLOWING redirects from http to https
215    *
216    * @param URL
217    * url
218    * @return HttpUrlConnection conn
219    */
 
220  2 toggle public static URLConnection openConnection(URL url) throws IOException
221    {
222  2 return openConnection(url, false);
223    }
224   
 
225  2 toggle public static URLConnection openConnection(URL url, boolean followAnyway)
226    throws IOException
227    {
228  2 if (url == null)
229    {
230  0 LaunchUtils.syserr(false, true,
231    "HttpUtils.openConnection(url) called with null url");
232  0 return null;
233    }
234  2 LaunchUtils.syserr(false, true,
235    "HttpUtils.openConnection(url) called with url="
236    + url.toString());
237  2 URLConnection conn = null;
238  2 String protocol = url.getProtocol();
239  2 if ("http".equals(protocol) || "https".equals(protocol))
240    {
241  0 HttpURLConnection conn0 = (HttpURLConnection) url.openConnection();
242  0 if (conn0 != null)
243    {
244  0 conn = HttpUtils.followConnection(conn0, followAnyway);
245    }
246    else
247    {
248  0 conn = conn0;
249    }
250    }
251    else
252    {
253  2 conn = url.openConnection();
254    }
255  2 return conn;
256    }
257   
258    /**
259    * wrapper to follow a URL connection ALLOWING redirects from http to https
260    * and return the followed InputStream
261    *
262    * @param URL
263    * url
264    * @return HttpUrlConnection conn
265    */
 
266  533 toggle public static InputStream openStream(URL url) throws IOException
267    {
268  533 return openStream(url, false);
269    }
270   
 
271  533 toggle public static InputStream openStream(URL url, boolean followAnyway)
272    throws IOException
273    {
274  533 if (url == null)
275    {
276  0 return null;
277    }
278  533 InputStream is = null;
279  533 String protocol = url.getProtocol();
280  533 if ("http".equals(protocol) || "https".equals(protocol))
281    {
282  373 HttpURLConnection conn = HttpUtils.followConnection(
283    (HttpURLConnection) url.openConnection(), followAnyway);
284  373 if (conn != null)
285    {
286  373 is = conn.getInputStream();
287    }
288    }
289    else
290    {
291  160 is = url.openStream();
292    }
293  430 return is;
294    }
295   
296    /**
297    * check if a jalview:// scheme URL is given
298    *
299    * @param String
300    * uri
301    * @return boolean
302    */
 
303  352 toggle public static boolean isJalviewSchemeUri(String jalviewUriString)
304    {
305  352 if (jalviewUriString == null)
306    {
307  0 return false;
308    }
309  352 URI jalviewUri;
310  352 try
311    {
312  352 jalviewUri = new URI(jalviewUriString);
313    } catch (URISyntaxException e)
314    {
315  0 return false;
316    }
317  352 String scheme = jalviewUri.getScheme();
318  352 if (scheme == null || !scheme.startsWith(JALVIEWSCHEMEPREFIX))
319    {
320  352 return false;
321    }
322  0 int jspl = JALVIEWSCHEMEPREFIX.length();
323  0 return scheme.length() == jspl // jalview
324    || scheme.length() == jspl + 1 // jalviewX
325    || scheme.substring(jspl).equals("http") // jalviewhttp
326    || scheme.substring(jspl).equals("https"); // jalviewhttps
327    }
328   
329    /**
330    * convert a jalview scheme URI to its equivalent URL or path
331    *
332    * @param String
333    * uri
334    * @return String
335    */
 
336  176 toggle public static String equivalentJalviewUrl(String jalviewUriString)
337    {
338  176 if (!isJalviewSchemeUri(jalviewUriString))
339    {
340    // not a jalviewUriString, hand it back
341  176 return jalviewUriString;
342    }
343  0 URI jalviewUri;
344  0 try
345    {
346  0 jalviewUri = new URI(jalviewUriString);
347    } catch (URISyntaxException e)
348    {
349  0 return null;
350    }
351  0 String scheme = jalviewUri.getScheme();
352  0 String host = jalviewUri.getHost();
353  0 if (host != null && host.length() > 0 || scheme
354    .substring(JALVIEWSCHEMEPREFIX.length()).startsWith("http"))
355    {
356  0 URI newUri;
357  0 try
358    {
359  0 newUri = new URI(
360  0 scheme.equals(JALVIEWSCHEMEPREFIX + "http") ? "http"
361    : "https",
362    jalviewUri.getUserInfo(), host, jalviewUri.getPort(),
363    jalviewUri.getPath(), jalviewUri.getQuery(),
364    jalviewUri.getFragment());
365    // return a URL
366  0 return newUri.toURL().toString();
367    } catch (URISyntaxException | MalformedURLException e)
368    {
369  0 ErrorLog.errPrintln("Trying to convert '" + jalviewUriString
370    + "' to URL failed");
371    }
372    }
373    else
374    {
375    // return a file path (not a file URI)
376  0 return jalviewUri.getPath();
377    }
378  0 return null;
379    }
380    }