package net.classicube.launcher;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
final class HttpUtil {
private static final int MaxRedirects = 3;
public static final String FORM_DATA = "application/x-www-form-urlencoded";
public static final String JSON = "application/json";
public static HttpURLConnection makeHttpConnection(final String urlString, final byte[] postData, final String contentType)
throws MalformedURLException, IOException {
if (urlString == null) {
throw new NullPointerException("urlString");
}
final URL url = new URL(urlString);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setUseCaches(false);
if (postData != null) {
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept-Charset", StandardCharsets.UTF_8.name());
connection.setRequestProperty("Content-Type", contentType);
connection.setRequestProperty("Content-Length", Integer.toString(postData.length));
connection.setDoOutput(true);
} else {
connection.setRequestMethod("GET");
}
connection.setRequestProperty("Referer", urlString);
connection.setRequestProperty("User-Agent", LogUtil.VERSION_STRING);
return connection;
}
// Downloads a string using GET.
// Returns null and logs an error on failure.
public static String downloadString(final String urlString) {
return uploadString(urlString, null, null, MaxRedirects);
}
// Uploads a string using POST, then downloads the response.
// Returns null and logs an error on failure.
public static String uploadString(final String urlString, final String dataString, final String contentType) {
return uploadString(urlString, dataString, contentType, MaxRedirects);
}
private static String uploadString(final String urlString, final String dataString,
final String contentType, final int followRedirects) {
LogUtil.getLogger().log(Level.FINE, "{0} {1}",
new Object[]{dataString == null ? "GET" : "POST", urlString});
HttpURLConnection connection = null;
final byte[] data;
if (dataString != null) {
data = dataString.getBytes();
} else {
data = null;
}
try {
// DEBUG: Log request headers
//LogUtil.getLogger().log(Level.INFO,connection.getRequestProperties().toString());
connection = HttpUtil.makeHttpConnection(urlString, data, contentType);
// Write POST (if needed)
if (data != null) {
try (OutputStream os = connection.getOutputStream()) {
os.write(data);
}
}
// DEBUG: Log response headers
//LogUtil.getLogger().log(Level.INFO,connection.getHeaderFields().toString());
// Handle redirects
final int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_MOVED_PERM
|| responseCode == HttpURLConnection.HTTP_MOVED_TEMP) {
if (followRedirects > 0) {
final String redirectUrl = connection.getHeaderField("location");
return uploadString(redirectUrl, null, contentType, followRedirects - 1);
} else {
LogUtil.getLogger().log(Level.FINE, "Redirected ({0}) to {1} (not following)",
new Object[]{responseCode, urlString});
}
}
// Read response
final StringBuilder response = new StringBuilder();
final boolean badRequest = (responseCode >= HttpURLConnection.HTTP_BAD_REQUEST);
try (final InputStream is = (badRequest ? connection.getErrorStream() : connection.getInputStream())) {
try (final InputStreamReader isr = new InputStreamReader(is)) {
try (final BufferedReader rd = new BufferedReader(isr)) {
String line;
while ((line = rd.readLine()) != null) {
response.append(line);
response.append(System.lineSeparator());
}
}
}
}
if (badRequest) {
String errMsg = String.format("Server returned HTTP response code: %d for URL: %s with message:%n%s",
responseCode, urlString, response);
throw new IOException(errMsg);
}
return response.toString();
} catch (final IOException ex) {
LogUtil.getLogger().log(Level.SEVERE, "Error while sending request to " + urlString, ex);
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
private HttpUtil() {
}
}