static ResultHandler throwOnError(ResultHandler okHandler) {
			return conn -> {
				if (conn instanceof HttpURLConnection) {
					HttpURLConnection httpConn = (HttpURLConnection) conn;
					int responseCode = httpConn.getResponseCode();
					if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
						String fileURL = conn.getURL().toExternalForm();
						throw new FileNotFoundException(
								"No file to download at " + fileURL + ". Server replied HTTP code: " + responseCode);
					} else if (responseCode >= 400) {
						String message = null;
						if (httpConn.getErrorStream() != null) {
							String err = new BufferedReader(new InputStreamReader(httpConn.getErrorStream()))
								.lines()
								.collect(
										Collectors.joining(
												"\n"))
								.trim();
							verboseMsg("HTTP: " + responseCode + " - " + err);
							if (err.startsWith("{") && err.endsWith("}")) {
								// Could be JSON, let's try to parse it
								try {
									Gson parser = new Gson();
									Map json = parser.fromJson(err, Map.class);
									// GitHub returns useful information in `message`,
									// if it's there we use it.
									// TODO add support for other known sites
									message = Objects.toString(json.get("message"));
								} catch (JsonSyntaxException ex) {
									// Not JSON it seems
								}
							}
						}
						if (message != null) {
							throw new IOException(
									String.format("Server returned HTTP response code: %d for URL: %s with message: %s",
											responseCode, conn.getURL().toString(), message));
						} else {
							throw new IOException(String.format("Server returned HTTP response code: %d for URL: %s",
									responseCode, conn.getURL().toString()));
						}
					}
				}
				return okHandler.handle(conn);
			};
		}
Downloads a file from a URL

@param fileURL HTTP URL of the file to be downloaded
@param saveDir path of the directory to save the file
@param timeOut the timeout in milliseconds to use for opening the connection.
               0 is an infinite timeout while -1 uses the defaults
@return Path to the downloaded file
@throws IOException
src/main/java/dev/jbang/util/Util.java