Rewrite encode location

This commit is contained in:
huanghongxun 2018-10-10 16:37:04 +08:00
parent 94727353c4
commit b12711969c

View File

@ -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<String, List<String>> 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 <a href="https://github.com/curl/curl/blob/3f7b1bb89f92c13e69ee51b710ac54f775aab320/lib/transfer.c#L1427-L1461">Curl</a>
* @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 <a href="https://github.com/curl/curl/issues/473">Issue with libcurl</a>
* @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<String, List<String>> 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;
}