Files
MCCustomSkinLoader/Common/source/customskinloader/utils/HttpRequestUtil.java
T

260 lines
11 KiB
Java
Raw Normal View History

2016-11-06 12:00:36 +08:00
package customskinloader.utils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
2016-11-11 19:48:42 +08:00
import java.net.URI;
2016-11-06 12:00:36 +08:00
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import customskinloader.CustomSkinLoader;
public class HttpRequestUtil {
2019-09-20 11:44:07 +08:00
public static class HttpRequest {
2018-02-12 12:20:28 +08:00
public String url;
2019-09-20 11:44:07 +08:00
public String userAgent = null;
public String payload = null;
public boolean loadContent = true;
public boolean checkPNG = false;
public int cacheTime = 600;//-1=No Cache 0=Always Cache t=Default Cache Time(second)
public File cacheFile = null;//Default Cache File
public HttpRequest(String url) {
this.url = url;
2018-02-12 12:20:28 +08:00
}
2019-09-20 11:44:07 +08:00
public HttpRequest setUserAgent(String userAgent) {
this.userAgent = userAgent;
2018-02-12 12:20:28 +08:00
return this;
}
2019-09-20 11:44:07 +08:00
public HttpRequest setPayload(String payload) {
this.payload = payload;
2018-02-12 12:20:28 +08:00
return this;
}
2019-09-20 11:44:07 +08:00
public HttpRequest setLoadContent(boolean loadContent) {
this.loadContent = loadContent;
2018-02-12 12:20:28 +08:00
return this;
}
2019-09-20 11:44:07 +08:00
public HttpRequest setCheckPNG(boolean checkPNG) {
this.checkPNG = checkPNG;
2018-02-12 12:20:28 +08:00
return this;
}
2019-09-20 11:44:07 +08:00
public HttpRequest setCacheTime(int cacheTime) {
this.cacheTime = cacheTime;
2018-02-12 12:20:28 +08:00
return this;
}
2019-09-20 11:44:07 +08:00
public HttpRequest setCacheFile(File cacheFile) {
this.cacheFile = cacheFile;
2018-02-12 12:20:28 +08:00
return this;
}
}
2019-09-20 11:44:07 +08:00
public static class HttpResponce {
public String content = null;
public int responceCode = -1;
public boolean success = false;
public boolean fromCache = false;
2018-02-12 12:20:28 +08:00
}
2019-09-20 11:44:07 +08:00
public static class CacheInfo {
2018-02-12 12:20:28 +08:00
public String url;
2019-09-20 11:44:07 +08:00
public String etag = null;
public long lastModified = -1;//ms
public long expire = -1;//UNIX timestamp
2018-02-12 12:20:28 +08:00
}
2019-09-20 11:44:07 +08:00
public static final File CACHE_DIR = new File(CustomSkinLoader.DATA_DIR, "caches");
public static HttpResponce makeHttpRequest(HttpRequest request) {
2019-03-03 11:34:54 +08:00
return makeHttpRequest(request, 0);
}
2019-09-20 11:44:07 +08:00
public static HttpResponce makeHttpRequest(HttpRequest request, int redirectTime) {
try {
2019-10-03 15:30:46 +08:00
if(request.url.contains("{ABORT}")){
CustomSkinLoader.logger.info("ABORT tag found in url, request has been aborted.");
return new HttpResponce();
}
2019-09-20 11:44:07 +08:00
CustomSkinLoader.logger.debug("Try to request '" + request.url + (request.userAgent == null ? "'." : "' with user agent '" + request.userAgent + "'."));
2018-02-12 12:20:28 +08:00
//Check Cache
2019-09-20 11:44:07 +08:00
if (StringUtils.isNotEmpty(request.payload))
request.cacheTime = -1;//No Cache
File cacheInfoFile = null;
CacheInfo cacheInfo = new CacheInfo();
if (request.cacheFile == null && request.cacheTime >= 0) {
String hash = DigestUtils.sha1Hex(request.url);
request.cacheFile = new File(CACHE_DIR, hash);
cacheInfoFile = new File(CACHE_DIR, hash + ".json");
2018-02-12 12:20:28 +08:00
}
2019-09-20 11:44:07 +08:00
if (request.cacheTime == 0 && request.cacheFile.isFile())
return loadFromCache(request, new HttpResponce());
if (cacheInfoFile != null && cacheInfoFile.isFile()) {
String json = FileUtils.readFileToString(cacheInfoFile, "UTF-8");
if (StringUtils.isNotEmpty(json))
cacheInfo = CustomSkinLoader.GSON.fromJson(json, CacheInfo.class);
if (cacheInfo == null)
cacheInfo = new CacheInfo();
if (cacheInfo.expire >= TimeUtil.getCurrentUnixTimestamp())
return loadFromCache(request, new HttpResponce(), cacheInfo.expire);
2018-02-12 12:20:28 +08:00
}
2019-09-20 11:44:07 +08:00
2018-02-12 12:20:28 +08:00
//Init Connection
URL rawUrl = new URL(request.url);
URI uri = new URI(
rawUrl.getProtocol(),
rawUrl.getUserInfo(),
rawUrl.getHost(),
rawUrl.getPort(),
rawUrl.getPath(),
rawUrl.getQuery(),
rawUrl.getRef()
);
String url = uri.toASCIIString();
2019-09-20 11:44:07 +08:00
if (!url.equalsIgnoreCase(request.url))
CustomSkinLoader.logger.debug("Encoded URL: " + url);
2018-02-12 12:20:28 +08:00
HttpURLConnection c = (HttpURLConnection) (new URL(url)).openConnection();
c.setReadTimeout(1000 * 10);
c.setConnectTimeout(1000 * 10);
c.setDoInput(true);
c.setUseCaches(false);
c.setInstanceFollowRedirects(true);
2019-09-20 11:44:07 +08:00
2018-02-12 12:20:28 +08:00
//Make Connection
2019-09-20 11:44:07 +08:00
if (cacheInfo.lastModified >= 0)
2018-02-12 12:20:28 +08:00
c.setIfModifiedSince(cacheInfo.lastModified);
2019-09-20 11:44:07 +08:00
if (cacheInfo.etag != null)
c.setRequestProperty("If-None-Match", cacheInfo.etag);
c.setRequestProperty("Accept-Encoding", "gzip");
if (request.userAgent != null)
c.setRequestProperty("User-Agent", request.userAgent);
if (StringUtils.isNotEmpty(request.payload)) {
CustomSkinLoader.logger.info("Payload: " + request.payload);
c.setRequestProperty("Content-Type", "application/json");
2018-02-12 12:20:28 +08:00
c.setDoOutput(true);
2019-09-20 11:44:07 +08:00
OutputStream os = c.getOutputStream();
2018-06-25 00:34:32 +08:00
IOUtils.write(request.payload, os, "UTF-8");
2018-02-12 12:20:28 +08:00
IOUtils.closeQuietly(os);
}
c.connect();
2019-09-20 11:44:07 +08:00
2018-02-12 12:20:28 +08:00
//Check Connection
2019-09-20 11:44:07 +08:00
HttpResponce responce = new HttpResponce();
responce.responceCode = c.getResponseCode();
2019-03-03 11:53:48 +08:00
int res = c.getResponseCode();
if (res / 100 == 4 || res / 100 == 5) {//Failed
CustomSkinLoader.logger.debug("Failed to request (Response Code: " + res + ")");
2018-02-12 12:20:28 +08:00
return responce;
}
2019-03-03 11:34:54 +08:00
if (res == HttpURLConnection.HTTP_MOVED_PERM || res == HttpURLConnection.HTTP_MOVED_TEMP) {
//Redirect
if (redirectTime >= 4) {
CustomSkinLoader.logger.debug("Failed to request (Too many redirection)");
2019-09-20 11:44:07 +08:00
return responce;
2019-03-03 11:34:54 +08:00
}
request.url = c.getHeaderField("Location");//Get redirecting location
if (request.url == null) {
CustomSkinLoader.logger.debug("Failed to request (Redirecting location not found)");
return responce;
}
2019-03-03 11:53:48 +08:00
CustomSkinLoader.logger.debug("Redirect to: " + request.url);
2019-03-03 11:34:54 +08:00
return makeHttpRequest(request, redirectTime + 1);//Recursion
}
2019-09-20 11:44:07 +08:00
responce.success = true;
2019-03-03 12:20:28 +08:00
CustomSkinLoader.logger.debug("Successfully request (Response Code: " + res + " , Content Length: " + c.getContentLength() + ")");
2019-09-20 11:44:07 +08:00
if (responce.responceCode == HttpURLConnection.HTTP_NOT_MODIFIED)
return loadFromCache(request, responce);
2019-02-06 00:39:17 +08:00
if (responce.responceCode == HttpURLConnection.HTTP_NO_CONTENT)
request.cacheTime = 3600;
2019-09-20 11:44:07 +08:00
2018-02-12 12:20:28 +08:00
//Load Content
2019-09-20 11:44:07 +08:00
InputStream is = "gzip".equals(c.getContentEncoding()) ? new GZIPInputStream(c.getInputStream()) : c.getInputStream();
byte[] bytes = IOUtils.toByteArray(is);
if (request.checkPNG && (bytes.length <= 4 || bytes[1] != (byte) 'P' || bytes[2] != (byte) 'N' || bytes[3] != (byte) 'G')) {
2018-02-12 15:02:12 +08:00
CustomSkinLoader.logger.debug("Failed to request (Not Standard PNG)");
2019-09-20 11:44:07 +08:00
responce.success = false;
2018-02-12 12:20:28 +08:00
return responce;
}
2019-09-20 11:44:07 +08:00
if (request.cacheFile != null) {
2018-02-12 12:20:28 +08:00
FileUtils.writeByteArrayToFile(request.cacheFile, bytes);
2019-09-20 11:44:07 +08:00
if (cacheInfoFile != null) {
cacheInfo.url = request.url;
cacheInfo.etag = c.getHeaderField("ETag");
cacheInfo.lastModified = c.getLastModified();
cacheInfo.expire = getExpire(c, request.cacheTime);
2018-06-25 00:34:32 +08:00
FileUtils.write(cacheInfoFile, CustomSkinLoader.GSON.toJson(cacheInfo), "UTF-8");
2018-02-12 12:20:28 +08:00
}
2019-09-20 11:44:07 +08:00
CustomSkinLoader.logger.debug("Saved to cache (Length: " + request.cacheFile.length() + " , Path: '" + request.cacheFile.getAbsolutePath() + "' , Expire: " + cacheInfo.expire + ")");
2018-02-12 12:20:28 +08:00
}
2019-09-20 11:44:07 +08:00
if (!request.loadContent)
2018-02-12 12:20:28 +08:00
return responce;
2019-09-20 11:44:07 +08:00
responce.content = new String(bytes, "UTF-8");
CustomSkinLoader.logger.debug("Content: " + responce.content);
2018-02-12 12:20:28 +08:00
return responce;
2019-09-20 11:44:07 +08:00
} catch (Exception e) {
2020-08-16 19:50:19 +08:00
CustomSkinLoader.logger.debug("Failed to request " + request.url + " (Exception: " + e.toString() + ")");
2019-09-20 11:44:07 +08:00
return loadFromCache(request, new HttpResponce());
2018-02-12 12:20:28 +08:00
}
}
2019-09-20 11:44:07 +08:00
public static File getCacheFile(String hash) {
return new File(CACHE_DIR, hash);
2018-02-12 12:20:28 +08:00
}
2019-09-20 11:44:07 +08:00
private static HttpResponce loadFromCache(HttpRequest request, HttpResponce responce) {
return loadFromCache(request, responce, 0);
2018-02-12 12:20:28 +08:00
}
2019-09-20 11:44:07 +08:00
private static HttpResponce loadFromCache(HttpRequest request, HttpResponce responce, long expireTime) {
if (request.cacheFile == null || !request.cacheFile.isFile())
2018-02-12 12:20:28 +08:00
return responce;
2020-08-16 19:50:19 +08:00
CustomSkinLoader.logger.debug("Cache file found (Length: " + request.cacheFile.length() + " , Path: '" + request.cacheFile.getAbsolutePath() + "' , Expire: " + expireTime + ")");
2019-09-20 11:44:07 +08:00
responce.fromCache = true;
responce.success = true;
if (!request.loadContent)
2018-02-12 12:20:28 +08:00
return responce;
2019-09-20 11:44:07 +08:00
CustomSkinLoader.logger.info("Try to load from cache '" + request.cacheFile.getAbsolutePath() + "'.");
2018-02-12 12:20:28 +08:00
try {
2019-09-20 11:44:07 +08:00
responce.content = FileUtils.readFileToString(request.cacheFile, "UTF-8");
2018-02-12 15:02:12 +08:00
CustomSkinLoader.logger.debug("Successfully load from cache");
2019-09-20 11:44:07 +08:00
CustomSkinLoader.logger.debug("Content: " + responce.content);
2018-02-12 12:20:28 +08:00
} catch (IOException e) {
2019-09-20 11:44:07 +08:00
CustomSkinLoader.logger.debug("Failed to load from cache (Exception: " + e.toString() + ")");
responce.success = false;
2018-02-12 12:20:28 +08:00
}
return responce;
}
2019-09-20 11:44:07 +08:00
2018-02-12 12:20:28 +08:00
private final static Pattern MAX_AGE_PATTERN = Pattern.compile(".*?max-age=(\\d+).*?");
2019-09-20 11:44:07 +08:00
private static long getExpire(HttpURLConnection connection, int cacheTime) {
String cacheControl = connection.getHeaderField("Cache-Control");
if (StringUtils.isNotEmpty(cacheControl)) {
Matcher m = MAX_AGE_PATTERN.matcher(cacheControl);
if (m.matches())
2018-02-12 12:20:28 +08:00
return TimeUtil.getUnixTimestamp(Long.parseLong(m.group(m.groupCount())));
}
2019-09-20 11:44:07 +08:00
long expires = connection.getExpiration();
if (expires > 0)
return expires / 1000;
return TimeUtil.getUnixTimestampRandomDelay(cacheTime == 0 ? 86400 : cacheTime);
2018-02-12 12:20:28 +08:00
}
2016-11-06 12:00:36 +08:00
}