Skip to content

Commit 481a452

Browse files
committed
Some changes to remove 404-responses from the webserver on empty map-tiles
1 parent bd5071e commit 481a452

File tree

7 files changed

+95
-75
lines changed

7 files changed

+95
-75
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ build/
44
bin/
55
doc/
66
logs/
7+
.run/
78
run/
89
node_modules/
910

BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/api/marker/MarkerImpl.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import de.bluecolored.bluemap.api.marker.Marker;
3232
import ninja.leaping.configurate.ConfigurationNode;
3333

34-
import java.util.Objects;
3534
import java.util.Optional;
3635

3736
public abstract class MarkerImpl implements Marker {

BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,7 @@
2424
*/
2525
package de.bluecolored.bluemap.common.plugin;
2626

27-
import java.io.DataInputStream;
28-
import java.io.DataOutputStream;
29-
import java.io.File;
30-
import java.io.FileInputStream;
31-
import java.io.FileOutputStream;
32-
import java.io.IOException;
33-
import java.util.Collection;
34-
import java.util.Map;
35-
import java.util.UUID;
36-
import java.util.concurrent.TimeUnit;
37-
import java.util.zip.GZIPInputStream;
38-
import java.util.zip.GZIPOutputStream;
39-
40-
import de.bluecolored.bluemap.common.BlueMapService;
41-
import de.bluecolored.bluemap.common.InterruptableReentrantLock;
42-
import de.bluecolored.bluemap.common.MapType;
43-
import de.bluecolored.bluemap.common.MissingResourcesException;
44-
import de.bluecolored.bluemap.common.RenderManager;
27+
import de.bluecolored.bluemap.common.*;
4528
import de.bluecolored.bluemap.common.api.BlueMapAPIImpl;
4629
import de.bluecolored.bluemap.common.live.LiveAPIRequestHandler;
4730
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
@@ -59,6 +42,14 @@
5942
import de.bluecolored.bluemap.core.webserver.WebServer;
6043
import de.bluecolored.bluemap.core.world.World;
6144

45+
import java.io.*;
46+
import java.util.Collection;
47+
import java.util.Map;
48+
import java.util.UUID;
49+
import java.util.concurrent.TimeUnit;
50+
import java.util.zip.GZIPInputStream;
51+
import java.util.zip.GZIPOutputStream;
52+
6253
public class Plugin {
6354

6455
public static final String PLUGIN_ID = "bluemap";
@@ -207,7 +198,10 @@ public void load() throws IOException, ParseResourceException {
207198

208199
//start skin updater
209200
if (pluginConfig.isLiveUpdatesEnabled()) {
210-
this.skinUpdater = new PlayerSkinUpdater(new File(renderConfig.getWebRoot(), "assets" + File.separator + "playerheads"));
201+
this.skinUpdater = new PlayerSkinUpdater(
202+
new File(renderConfig.getWebRoot(), "assets" + File.separator + "playerheads"),
203+
new File(renderConfig.getWebRoot(), "assets" + File.separator + "steve.png")
204+
);
211205
serverInterface.registerListener(skinUpdater);
212206
}
213207

BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/skins/PlayerSkin.java

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@
2424
*/
2525
package de.bluecolored.bluemap.common.plugin.skins;
2626

27-
import java.awt.Graphics2D;
27+
import com.google.gson.JsonArray;
28+
import com.google.gson.JsonElement;
29+
import com.google.gson.JsonParser;
30+
import de.bluecolored.bluemap.core.logger.Logger;
31+
32+
import javax.imageio.ImageIO;
33+
import java.awt.*;
2834
import java.awt.image.BufferedImage;
2935
import java.io.File;
3036
import java.io.IOException;
@@ -33,19 +39,7 @@
3339
import java.net.URL;
3440
import java.util.Base64;
3541
import java.util.UUID;
36-
import java.util.concurrent.CompletableFuture;
37-
import java.util.concurrent.ExecutionException;
38-
import java.util.concurrent.Future;
39-
import java.util.concurrent.TimeUnit;
40-
import java.util.concurrent.TimeoutException;
41-
42-
import javax.imageio.ImageIO;
43-
44-
import com.google.gson.JsonArray;
45-
import com.google.gson.JsonElement;
46-
import com.google.gson.JsonParser;
47-
48-
import de.bluecolored.bluemap.core.logger.Logger;
42+
import java.util.concurrent.*;
4943

5044
public class PlayerSkin {
5145

@@ -57,23 +51,32 @@ public PlayerSkin(UUID uuid) {
5751
this.lastUpdate = -1;
5852
}
5953

60-
public void update(File storageFolder) {
54+
public void update(File storageFolder, File fallback) {
6155
long now = System.currentTimeMillis();
6256
if (lastUpdate > 0 && lastUpdate + 600000 > now) return; // only update if skin is older than 10 minutes
6357

6458
lastUpdate = now;
6559

6660
new Thread(() -> {
61+
BufferedImage head = null;
62+
6763
try {
6864
Future<BufferedImage> futureSkin = loadSkin();
6965
BufferedImage skin = futureSkin.get(10, TimeUnit.SECONDS);
70-
BufferedImage head = createHead(skin);
71-
ImageIO.write(head, "png", new File(storageFolder, uuid.toString() + ".png"));
66+
head = createHead(skin);
7267
} catch (ExecutionException | TimeoutException e) {
7368
Logger.global.logDebug("Failed to load player-skin from mojang-servers: " + e);
69+
} catch (InterruptedException ignore) {
70+
Thread.currentThread().interrupt();
71+
return;
72+
}
73+
74+
try {
75+
if (head == null) head = ImageIO.read(fallback);
76+
ImageIO.write(head, "png", new File(storageFolder, uuid.toString() + ".png"));
7477
} catch (IOException e) {
7578
Logger.global.logError("Failed to write player-head image!", e);
76-
} catch (InterruptedException ignore) { Thread.currentThread().interrupt(); }
79+
}
7780
}).start();
7881
}
7982

BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/skins/PlayerSkinUpdater.java

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,28 @@
2424
*/
2525
package de.bluecolored.bluemap.common.plugin.skins;
2626

27+
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
28+
import org.apache.commons.io.FileUtils;
29+
2730
import java.io.File;
31+
import java.io.IOException;
2832
import java.util.Map;
2933
import java.util.UUID;
3034
import java.util.concurrent.ConcurrentHashMap;
3135

32-
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
33-
3436
public class PlayerSkinUpdater implements ServerEventListener {
3537

3638
private File storageFolder;
39+
private File defaultSkin;
3740

38-
private Map<UUID, PlayerSkin> skins;
41+
private final Map<UUID, PlayerSkin> skins;
3942

40-
public PlayerSkinUpdater(File storageFolder) {
43+
public PlayerSkinUpdater(File storageFolder, File defaultSkin) throws IOException {
4144
this.storageFolder = storageFolder;
45+
this.defaultSkin = defaultSkin;
4246
this.skins = new ConcurrentHashMap<>();
43-
44-
this.storageFolder.mkdirs();
47+
48+
FileUtils.forceMkdir(this.storageFolder);
4549
}
4650

4751
public void updateSkin(UUID playerUuid) {
@@ -52,12 +56,28 @@ public void updateSkin(UUID playerUuid) {
5256
skins.put(playerUuid, skin);
5357
}
5458

55-
skin.update(storageFolder);
59+
skin.update(storageFolder, defaultSkin);
5660
}
5761

5862
@Override
5963
public void onPlayerJoin(UUID playerUuid) {
6064
updateSkin(playerUuid);
6165
}
62-
66+
67+
public File getStorageFolder() {
68+
return storageFolder;
69+
}
70+
71+
public void setStorageFolder(File storageFolder) {
72+
this.storageFolder = storageFolder;
73+
}
74+
75+
public File getDefaultSkin() {
76+
return defaultSkin;
77+
}
78+
79+
public void setDefaultSkin(File defaultSkin) {
80+
this.defaultSkin = defaultSkin;
81+
}
82+
6383
}

BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/FileRequestHandler.java

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
*/
2525
package de.bluecolored.bluemap.core.web;
2626

27-
import java.io.ByteArrayInputStream;
28-
import java.io.ByteArrayOutputStream;
29-
import java.io.File;
30-
import java.io.FileInputStream;
31-
import java.io.FileNotFoundException;
32-
import java.io.IOException;
27+
import de.bluecolored.bluemap.core.webserver.HttpRequest;
28+
import de.bluecolored.bluemap.core.webserver.HttpRequestHandler;
29+
import de.bluecolored.bluemap.core.webserver.HttpResponse;
30+
import de.bluecolored.bluemap.core.webserver.HttpStatusCode;
31+
import org.apache.commons.io.IOUtils;
32+
import org.apache.commons.lang3.time.DateFormatUtils;
33+
34+
import java.io.*;
3335
import java.nio.file.InvalidPathException;
3436
import java.nio.file.Path;
3537
import java.util.GregorianCalendar;
@@ -40,26 +42,22 @@
4042
import java.util.zip.GZIPInputStream;
4143
import java.util.zip.GZIPOutputStream;
4244

43-
import org.apache.commons.io.IOUtils;
44-
import org.apache.commons.lang3.time.DateFormatUtils;
45-
46-
import de.bluecolored.bluemap.core.webserver.HttpRequest;
47-
import de.bluecolored.bluemap.core.webserver.HttpRequestHandler;
48-
import de.bluecolored.bluemap.core.webserver.HttpResponse;
49-
import de.bluecolored.bluemap.core.webserver.HttpStatusCode;
50-
5145
public class FileRequestHandler implements HttpRequestHandler {
5246

5347
private static final long DEFLATE_MIN_SIZE = 10L * 1024L;
5448
private static final long DEFLATE_MAX_SIZE = 10L * 1024L * 1024L;
5549
private static final long INFLATE_MAX_SIZE = 10L * 1024L * 1024L;
5650

57-
private Path webRoot;
58-
private String serverName;
51+
private final Path webRoot;
52+
private final String serverName;
53+
54+
private final File emptyTileFile;
5955

6056
public FileRequestHandler(Path webRoot, String serverName) {
61-
this.webRoot = webRoot;
57+
this.webRoot = webRoot.normalize();
6258
this.serverName = serverName;
59+
60+
this.emptyTileFile = webRoot.resolve("assets").resolve("emptyTile.json").toFile();
6361
}
6462

6563
@Override
@@ -84,23 +82,23 @@ public HttpResponse handle(HttpRequest request) {
8482
private HttpResponse generateResponse(HttpRequest request) {
8583
String path = request.getPath();
8684

87-
//normalize path
85+
// normalize path
8886
if (path.startsWith("/")) path = path.substring(1);
8987
if (path.endsWith("/")) path = path.substring(0, path.length() - 1);
90-
88+
9189
Path filePath = webRoot;
9290
try {
9391
filePath = webRoot.resolve(path);
9492
} catch (InvalidPathException e){
9593
return new HttpResponse(HttpStatusCode.NOT_FOUND);
9694
}
9795

98-
//can we use deflation?
96+
// can we use deflation?
9997
boolean isDeflationPossible = request.getLowercaseHeader("Accept-Encoding").contains("gzip");
10098
boolean isDeflated = false;
10199

102-
//check if file is in web-root
103-
if (!filePath.normalize().startsWith(webRoot.normalize())){
100+
// check if file is in web-root
101+
if (!filePath.normalize().startsWith(webRoot)){
104102
return new HttpResponse(HttpStatusCode.FORBIDDEN);
105103
}
106104

@@ -128,7 +126,12 @@ private HttpResponse generateResponse(HttpRequest request) {
128126
isDeflated = true;
129127
}
130128

131-
if (!file.exists()){
129+
if (!file.exists() && file.toPath().startsWith(webRoot.resolve("data"))){
130+
file = emptyTileFile;
131+
isDeflated = false;
132+
}
133+
134+
if (!file.exists() || file.isDirectory()) {
132135
return new HttpResponse(HttpStatusCode.NOT_FOUND);
133136
}
134137

@@ -140,12 +143,12 @@ private HttpResponse generateResponse(HttpRequest request) {
140143
}
141144
}
142145

143-
//check if file is still in web-root
144-
if (!file.toPath().normalize().startsWith(webRoot.normalize())){
146+
// check if file is still in web-root and is not a directory
147+
if (!file.toPath().normalize().startsWith(webRoot) || file.isDirectory()){
145148
return new HttpResponse(HttpStatusCode.FORBIDDEN);
146149
}
147150

148-
//check modified
151+
// check modified
149152
long lastModified = file.lastModified();
150153
Set<String> modStringSet = request.getHeader("If-Modified-Since");
151154
if (!modStringSet.isEmpty()){
@@ -154,7 +157,7 @@ private HttpResponse generateResponse(HttpRequest request) {
154157
if (since + 1000 >= lastModified){
155158
return new HttpResponse(HttpStatusCode.NOT_MODIFIED);
156159
}
157-
} catch (IllegalArgumentException e){}
160+
} catch (IllegalArgumentException ignored){}
158161
}
159162

160163
//check ETag
@@ -174,7 +177,7 @@ private HttpResponse generateResponse(HttpRequest request) {
174177
response.addHeader("Cache-Control", "max-age=" + TimeUnit.HOURS.toSeconds(1));
175178

176179
//add content type header
177-
String filetype = file.getName().toString();
180+
String filetype = file.getName();
178181
if (filetype.endsWith(".gz")) filetype = filetype.substring(0, filetype.length() - 3);
179182
int pointIndex = filetype.lastIndexOf('.');
180183
if (pointIndex >= 0) filetype = filetype.substring(pointIndex + 1);

0 commit comments

Comments
 (0)