forked from mirror/BlueMap
Some changes to remove 404-responses from the webserver on empty map-tiles
This commit is contained in:
parent
bd5071eb61
commit
481a452b9c
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@ build/
|
||||
bin/
|
||||
doc/
|
||||
logs/
|
||||
.run/
|
||||
run/
|
||||
node_modules/
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit f3dc8d5dd478475cf8a1f0f1b166843821109ad2
|
||||
Subproject commit 4bef101c6ee6ddef23049287cc1a3736d954979e
|
@ -31,7 +31,6 @@
|
||||
import de.bluecolored.bluemap.api.marker.Marker;
|
||||
import ninja.leaping.configurate.ConfigurationNode;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class MarkerImpl implements Marker {
|
||||
|
@ -24,24 +24,7 @@
|
||||
*/
|
||||
package de.bluecolored.bluemap.common.plugin;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import de.bluecolored.bluemap.common.BlueMapService;
|
||||
import de.bluecolored.bluemap.common.InterruptableReentrantLock;
|
||||
import de.bluecolored.bluemap.common.MapType;
|
||||
import de.bluecolored.bluemap.common.MissingResourcesException;
|
||||
import de.bluecolored.bluemap.common.RenderManager;
|
||||
import de.bluecolored.bluemap.common.*;
|
||||
import de.bluecolored.bluemap.common.api.BlueMapAPIImpl;
|
||||
import de.bluecolored.bluemap.common.live.LiveAPIRequestHandler;
|
||||
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
|
||||
@ -59,6 +42,14 @@
|
||||
import de.bluecolored.bluemap.core.webserver.WebServer;
|
||||
import de.bluecolored.bluemap.core.world.World;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class Plugin {
|
||||
|
||||
public static final String PLUGIN_ID = "bluemap";
|
||||
@ -207,7 +198,10 @@ public void load() throws IOException, ParseResourceException {
|
||||
|
||||
//start skin updater
|
||||
if (pluginConfig.isLiveUpdatesEnabled()) {
|
||||
this.skinUpdater = new PlayerSkinUpdater(new File(renderConfig.getWebRoot(), "assets" + File.separator + "playerheads"));
|
||||
this.skinUpdater = new PlayerSkinUpdater(
|
||||
new File(renderConfig.getWebRoot(), "assets" + File.separator + "playerheads"),
|
||||
new File(renderConfig.getWebRoot(), "assets" + File.separator + "steve.png")
|
||||
);
|
||||
serverInterface.registerListener(skinUpdater);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,13 @@
|
||||
*/
|
||||
package de.bluecolored.bluemap.common.plugin.skins;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -33,19 +39,7 @@
|
||||
import java.net.URL;
|
||||
import java.util.Base64;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class PlayerSkin {
|
||||
|
||||
@ -57,23 +51,32 @@ public PlayerSkin(UUID uuid) {
|
||||
this.lastUpdate = -1;
|
||||
}
|
||||
|
||||
public void update(File storageFolder) {
|
||||
public void update(File storageFolder, File fallback) {
|
||||
long now = System.currentTimeMillis();
|
||||
if (lastUpdate > 0 && lastUpdate + 600000 > now) return; // only update if skin is older than 10 minutes
|
||||
|
||||
lastUpdate = now;
|
||||
|
||||
new Thread(() -> {
|
||||
BufferedImage head = null;
|
||||
|
||||
try {
|
||||
Future<BufferedImage> futureSkin = loadSkin();
|
||||
BufferedImage skin = futureSkin.get(10, TimeUnit.SECONDS);
|
||||
BufferedImage head = createHead(skin);
|
||||
ImageIO.write(head, "png", new File(storageFolder, uuid.toString() + ".png"));
|
||||
head = createHead(skin);
|
||||
} catch (ExecutionException | TimeoutException e) {
|
||||
Logger.global.logDebug("Failed to load player-skin from mojang-servers: " + e);
|
||||
} catch (InterruptedException ignore) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (head == null) head = ImageIO.read(fallback);
|
||||
ImageIO.write(head, "png", new File(storageFolder, uuid.toString() + ".png"));
|
||||
} catch (IOException e) {
|
||||
Logger.global.logError("Failed to write player-head image!", e);
|
||||
} catch (InterruptedException ignore) { Thread.currentThread().interrupt(); }
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
@ -24,24 +24,28 @@
|
||||
*/
|
||||
package de.bluecolored.bluemap.common.plugin.skins;
|
||||
|
||||
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
|
||||
|
||||
public class PlayerSkinUpdater implements ServerEventListener {
|
||||
|
||||
private File storageFolder;
|
||||
private File defaultSkin;
|
||||
|
||||
private Map<UUID, PlayerSkin> skins;
|
||||
private final Map<UUID, PlayerSkin> skins;
|
||||
|
||||
public PlayerSkinUpdater(File storageFolder) {
|
||||
public PlayerSkinUpdater(File storageFolder, File defaultSkin) throws IOException {
|
||||
this.storageFolder = storageFolder;
|
||||
this.defaultSkin = defaultSkin;
|
||||
this.skins = new ConcurrentHashMap<>();
|
||||
|
||||
this.storageFolder.mkdirs();
|
||||
|
||||
FileUtils.forceMkdir(this.storageFolder);
|
||||
}
|
||||
|
||||
public void updateSkin(UUID playerUuid) {
|
||||
@ -52,12 +56,28 @@ public void updateSkin(UUID playerUuid) {
|
||||
skins.put(playerUuid, skin);
|
||||
}
|
||||
|
||||
skin.update(storageFolder);
|
||||
skin.update(storageFolder, defaultSkin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerJoin(UUID playerUuid) {
|
||||
updateSkin(playerUuid);
|
||||
}
|
||||
|
||||
|
||||
public File getStorageFolder() {
|
||||
return storageFolder;
|
||||
}
|
||||
|
||||
public void setStorageFolder(File storageFolder) {
|
||||
this.storageFolder = storageFolder;
|
||||
}
|
||||
|
||||
public File getDefaultSkin() {
|
||||
return defaultSkin;
|
||||
}
|
||||
|
||||
public void setDefaultSkin(File defaultSkin) {
|
||||
this.defaultSkin = defaultSkin;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,12 +24,14 @@
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.web;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import de.bluecolored.bluemap.core.webserver.HttpRequest;
|
||||
import de.bluecolored.bluemap.core.webserver.HttpRequestHandler;
|
||||
import de.bluecolored.bluemap.core.webserver.HttpResponse;
|
||||
import de.bluecolored.bluemap.core.webserver.HttpStatusCode;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.GregorianCalendar;
|
||||
@ -40,26 +42,22 @@
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
|
||||
import de.bluecolored.bluemap.core.webserver.HttpRequest;
|
||||
import de.bluecolored.bluemap.core.webserver.HttpRequestHandler;
|
||||
import de.bluecolored.bluemap.core.webserver.HttpResponse;
|
||||
import de.bluecolored.bluemap.core.webserver.HttpStatusCode;
|
||||
|
||||
public class FileRequestHandler implements HttpRequestHandler {
|
||||
|
||||
private static final long DEFLATE_MIN_SIZE = 10L * 1024L;
|
||||
private static final long DEFLATE_MAX_SIZE = 10L * 1024L * 1024L;
|
||||
private static final long INFLATE_MAX_SIZE = 10L * 1024L * 1024L;
|
||||
|
||||
private Path webRoot;
|
||||
private String serverName;
|
||||
private final Path webRoot;
|
||||
private final String serverName;
|
||||
|
||||
private final File emptyTileFile;
|
||||
|
||||
public FileRequestHandler(Path webRoot, String serverName) {
|
||||
this.webRoot = webRoot;
|
||||
this.webRoot = webRoot.normalize();
|
||||
this.serverName = serverName;
|
||||
|
||||
this.emptyTileFile = webRoot.resolve("assets").resolve("emptyTile.json").toFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -84,10 +82,10 @@ public HttpResponse handle(HttpRequest request) {
|
||||
private HttpResponse generateResponse(HttpRequest request) {
|
||||
String path = request.getPath();
|
||||
|
||||
//normalize path
|
||||
// normalize path
|
||||
if (path.startsWith("/")) path = path.substring(1);
|
||||
if (path.endsWith("/")) path = path.substring(0, path.length() - 1);
|
||||
|
||||
|
||||
Path filePath = webRoot;
|
||||
try {
|
||||
filePath = webRoot.resolve(path);
|
||||
@ -95,12 +93,12 @@ private HttpResponse generateResponse(HttpRequest request) {
|
||||
return new HttpResponse(HttpStatusCode.NOT_FOUND);
|
||||
}
|
||||
|
||||
//can we use deflation?
|
||||
// can we use deflation?
|
||||
boolean isDeflationPossible = request.getLowercaseHeader("Accept-Encoding").contains("gzip");
|
||||
boolean isDeflated = false;
|
||||
|
||||
//check if file is in web-root
|
||||
if (!filePath.normalize().startsWith(webRoot.normalize())){
|
||||
// check if file is in web-root
|
||||
if (!filePath.normalize().startsWith(webRoot)){
|
||||
return new HttpResponse(HttpStatusCode.FORBIDDEN);
|
||||
}
|
||||
|
||||
@ -128,7 +126,12 @@ private HttpResponse generateResponse(HttpRequest request) {
|
||||
isDeflated = true;
|
||||
}
|
||||
|
||||
if (!file.exists()){
|
||||
if (!file.exists() && file.toPath().startsWith(webRoot.resolve("data"))){
|
||||
file = emptyTileFile;
|
||||
isDeflated = false;
|
||||
}
|
||||
|
||||
if (!file.exists() || file.isDirectory()) {
|
||||
return new HttpResponse(HttpStatusCode.NOT_FOUND);
|
||||
}
|
||||
|
||||
@ -140,12 +143,12 @@ private HttpResponse generateResponse(HttpRequest request) {
|
||||
}
|
||||
}
|
||||
|
||||
//check if file is still in web-root
|
||||
if (!file.toPath().normalize().startsWith(webRoot.normalize())){
|
||||
// check if file is still in web-root and is not a directory
|
||||
if (!file.toPath().normalize().startsWith(webRoot) || file.isDirectory()){
|
||||
return new HttpResponse(HttpStatusCode.FORBIDDEN);
|
||||
}
|
||||
|
||||
//check modified
|
||||
// check modified
|
||||
long lastModified = file.lastModified();
|
||||
Set<String> modStringSet = request.getHeader("If-Modified-Since");
|
||||
if (!modStringSet.isEmpty()){
|
||||
@ -154,7 +157,7 @@ private HttpResponse generateResponse(HttpRequest request) {
|
||||
if (since + 1000 >= lastModified){
|
||||
return new HttpResponse(HttpStatusCode.NOT_MODIFIED);
|
||||
}
|
||||
} catch (IllegalArgumentException e){}
|
||||
} catch (IllegalArgumentException ignored){}
|
||||
}
|
||||
|
||||
//check ETag
|
||||
@ -174,7 +177,7 @@ private HttpResponse generateResponse(HttpRequest request) {
|
||||
response.addHeader("Cache-Control", "max-age=" + TimeUnit.HOURS.toSeconds(1));
|
||||
|
||||
//add content type header
|
||||
String filetype = file.getName().toString();
|
||||
String filetype = file.getName();
|
||||
if (filetype.endsWith(".gz")) filetype = filetype.substring(0, filetype.length() - 3);
|
||||
int pointIndex = filetype.lastIndexOf('.');
|
||||
if (pointIndex >= 0) filetype = filetype.substring(pointIndex + 1);
|
||||
|
Loading…
Reference in New Issue
Block a user