diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java index c044c9c9c..d77d0958b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java @@ -19,6 +19,7 @@ package org.jackhuang.hmcl.util.io; import java.io.*; import java.net.*; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -64,20 +65,66 @@ public final class NetworkUtils { return connection; } - public static HttpURLConnection resolveConnection(HttpURLConnection conn) throws IOException { - conn.setUseCaches(false); - conn.setConnectTimeout(15000); - conn.setReadTimeout(15000); - conn.setInstanceFollowRedirects(false); - Map> properties = conn.getRequestProperties(); - int code = conn.getResponseCode(); - if (code >= 300 && code <= 307 && code != 306 && code != 304) { - String newURL = conn.getHeaderField("Location").replace(" ", "%20"); - conn.disconnect(); + /** + * @see Curl + * @param location + * @return + */ + public static String encodeLocation(String location) { + StringBuilder sb = new StringBuilder(); + boolean left = true; + for (char ch : location.toCharArray()) { + switch (ch) { + case ' ': + if (left) sb.append("%20"); + else sb.append('+'); + break; + case '?': + left = false; + default: + if (ch >= 0x80) + sb.append(encodeURL(Character.toString(ch))); + else + sb.append(ch); + break; + } + } - HttpURLConnection redirected = (HttpURLConnection) new URL(conn.getURL(), newURL).openConnection(); - properties.forEach((key, value) -> value.forEach(element -> redirected.addRequestProperty(key, element))); - return resolveConnection(redirected); + return sb.toString(); + } + + /** + * This method aims to solve problem when "Location" in stupid server's response is not encoded. + * @see Issue with libcurl + * @param conn + * @return + * @throws IOException + */ + public static HttpURLConnection resolveConnection(HttpURLConnection conn) throws IOException { + int redirect = 0; + while (true) { + + conn.setUseCaches(false); + conn.setConnectTimeout(15000); + conn.setReadTimeout(15000); + conn.setInstanceFollowRedirects(false); + Map> properties = conn.getRequestProperties(); + int code = conn.getResponseCode(); + if (code >= 300 && code <= 307 && code != 306 && code != 304) { + String newURL = conn.getHeaderField("Location"); + conn.disconnect(); + + if (redirect > 20) { + throw new IOException("Too much redirects"); + } + + HttpURLConnection redirected = (HttpURLConnection) new URL(conn.getURL(), encodeLocation(newURL)).openConnection(); + properties.forEach((key, value) -> value.forEach(element -> redirected.addRequestProperty(key, element))); + conn = redirected; + ++redirect; + } else { + break; + } } return conn; }