From 9b3c311e99725b4178d227e2c315258a06299e2b Mon Sep 17 00:00:00 2001 From: Ciaran Moran Date: Sat, 12 Sep 2026 22:25:39 +0100 Subject: [PATCH 1/3] Allow adding additional headers when serving static files --- .../bluemap/common/config/WebserverConfig.java | 3 +++ .../bluecolored/bluemap/common/plugin/Plugin.java | 12 +++++++++--- .../bluemap/common/web/FileRequestHandler.java | 14 +++++++++++--- .../bluemap/common/web/MapRequestHandler.java | 15 +++++++++------ .../common/web/MapStorageRequestHandler.java | 9 +++++++++ .../de/bluecolored/bluemap/config/webserver.conf | 11 ++++++++++- .../de/bluecolored/bluemap/cli/BlueMapCLI.java | 6 +++--- 7 files changed, 54 insertions(+), 16 deletions(-) diff --git a/common/src/main/java/de/bluecolored/bluemap/common/config/WebserverConfig.java b/common/src/main/java/de/bluecolored/bluemap/common/config/WebserverConfig.java index 4cef22e5b..cb7090c56 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/config/WebserverConfig.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/config/WebserverConfig.java @@ -31,6 +31,7 @@ import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.nio.file.Path; +import java.util.Map; @SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal"}) @ConfigSerializable @@ -47,6 +48,8 @@ public class WebserverConfig { private LogConfig log = new LogConfig(); + private Map additionalHeaders = Map.of(); + public InetAddress resolveIp() throws UnknownHostException { if (ip.isEmpty() || ip.equals("0.0.0.0") || ip.equals("::0")) { return new InetSocketAddress(0).getAddress(); diff --git a/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java b/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java index 7f74a53de..95cc3cd96 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java @@ -218,7 +218,7 @@ private void load(@Nullable ResourcePack preloadedResourcePack) throws IOExcepti this.webRequestHandler = new RoutingRequestHandler(); // default route - webRequestHandler.register(".*", new FileRequestHandler(webroot)); + webRequestHandler.register(".*", new FileRequestHandler(webroot, webserverConfig.getAdditionalHeaders())); // map route for (var mapConfigEntry : configManager.getMapConfigs().entrySet()) { @@ -233,10 +233,16 @@ private void load(@Nullable ResourcePack preloadedResourcePack) throws IOExcepti null; LiveMarkersDataSupplier liveMarkersDataSupplier = new LiveMarkersDataSupplier(map.getMarkerSets()); - mapRequestHandler = new MapRequestHandler(map, livePlayersDataSupplier, liveMarkersDataSupplier, webserverConfig.isSseEnabled()); + mapRequestHandler = new MapRequestHandler( + map, + livePlayersDataSupplier, + liveMarkersDataSupplier, + webserverConfig.isSseEnabled(), + webserverConfig.getAdditionalHeaders() + ); } else { Storage storage = blueMap.getOrLoadStorage(mapConfig.getStorage()); - mapRequestHandler = new MapRequestHandler(storage.map(id)); + mapRequestHandler = new MapRequestHandler(storage.map(id), webserverConfig.getAdditionalHeaders()); } webRequestHandler.register( diff --git a/common/src/main/java/de/bluecolored/bluemap/common/web/FileRequestHandler.java b/common/src/main/java/de/bluecolored/bluemap/common/web/FileRequestHandler.java index 0aaa86cbd..0809c8754 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/web/FileRequestHandler.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/web/FileRequestHandler.java @@ -26,6 +26,7 @@ import de.bluecolored.bluemap.common.web.http.*; import de.bluecolored.bluemap.core.logger.Logger; +import java.util.Map; import lombok.Getter; import lombok.NonNull; import lombok.Setter; @@ -45,9 +46,11 @@ public class FileRequestHandler implements HttpRequestHandler { private @NonNull Path webRoot; + private @NonNull Map additionalHeaders; - public FileRequestHandler(Path webRoot) { + public FileRequestHandler(Path webRoot, Map additionalHeaders) { this.webRoot = webRoot.normalize(); + this.additionalHeaders = additionalHeaders; } @Override @@ -135,13 +138,18 @@ private HttpResponse generateResponse(HttpRequest request) throws IOException { //create response HttpResponse response = new HttpResponse(HttpStatusCode.OK); + + response.addHeader("Cache-Control", "public"); + response.addHeader("Cache-Control", "max-age=" + TimeUnit.DAYS.toSeconds(1)); + + additionalHeaders.forEach(response::addHeader); + + //headers after here will not be overwritten by additional headers from config response.addHeader("ETag", eTag); if (lastModified > 0) response.addHeader("Last-Modified", DateTimeFormatter.RFC_1123_DATE_TIME.format(Instant .ofEpochMilli(lastModified) .atOffset(ZoneOffset.UTC) )); - response.addHeader("Cache-Control", "public"); - response.addHeader("Cache-Control", "max-age=" + TimeUnit.DAYS.toSeconds(1)); //add content type header String filetype = filePath.getFileName().toString(); diff --git a/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java b/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java index efb82932f..1193cf953 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java @@ -28,6 +28,7 @@ import de.bluecolored.bluemap.common.web.http.HttpStatusCode; import de.bluecolored.bluemap.core.map.BmMap; import de.bluecolored.bluemap.core.storage.MapStorage; +import java.util.Map; import org.jetbrains.annotations.Nullable; import com.flowpowered.math.vector.Vector2i; @@ -48,9 +49,10 @@ public MapRequestHandler( BmMap map, @Nullable Supplier livePlayersDataSupplier, @Nullable Supplier liveMarkerDataSupplier, - boolean useSSE + boolean useSSE, + Map additionalHeaders ) { - this(map.getStorage(), livePlayersDataSupplier, liveMarkerDataSupplier, useSSE); + this(map.getStorage(), livePlayersDataSupplier, liveMarkerDataSupplier, useSSE, additionalHeaders); if (useSSE) { map.getHiresModelManager().addTileUpdateListener(tile -> onTileUpdate(tile, 0)); @@ -58,17 +60,18 @@ public MapRequestHandler( } } - public MapRequestHandler(MapStorage mapStorage) { - this(mapStorage, null, null, false); + public MapRequestHandler(MapStorage mapStorage, Map additionalHeaders) { + this(mapStorage, null, null, false, additionalHeaders); } public MapRequestHandler( MapStorage mapStorage, @Nullable Supplier livePlayersDataSupplier, @Nullable Supplier liveMarkerDataSupplier, - boolean useSSE + boolean useSSE, + Map additionalHeaders ) { - register(".*", new MapStorageRequestHandler(mapStorage)); + register(".*", new MapStorageRequestHandler(mapStorage, additionalHeaders)); if (useSSE) { register("live/sse", "", _ -> { diff --git a/common/src/main/java/de/bluecolored/bluemap/common/web/MapStorageRequestHandler.java b/common/src/main/java/de/bluecolored/bluemap/common/web/MapStorageRequestHandler.java index 48951cdce..bdc79e532 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/web/MapStorageRequestHandler.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/web/MapStorageRequestHandler.java @@ -47,6 +47,7 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.Map; @RequiredArgsConstructor @Getter @Setter @@ -55,6 +56,7 @@ public class MapStorageRequestHandler implements HttpRequestHandler { private static final Pattern TILE_PATTERN = Pattern.compile("tiles/([\\d/]+)/x(-?[\\d/]+)z(-?[\\d/]+).*"); private @NonNull MapStorage mapStorage; + private @NonNull Map additionalHeaders; @Override public HttpResponse handle(HttpRequest request) { @@ -88,6 +90,9 @@ public HttpResponse handle(HttpRequest request) { response.addHeader("Cache-Control", "public"); response.addHeader("Cache-Control", "max-age=" + TimeUnit.DAYS.toSeconds(1)); + additionalHeaders.forEach(response::addHeader); + + //headers after here will not be overwritten by additional headers from config if (lod == 0) response.addHeader("Content-Type", "application/octet-stream"); else response.addHeader("Content-Type", "image/png"); @@ -107,6 +112,10 @@ public HttpResponse handle(HttpRequest request) { HttpResponse response = new HttpResponse(HttpStatusCode.OK); response.addHeader("Cache-Control", "public"); response.addHeader("Cache-Control", "max-age=" + TimeUnit.DAYS.toSeconds(1)); + + additionalHeaders.forEach(response::addHeader); + + //headers after here will not be overwritten by additional headers from config response.addHeader("Content-Type", ContentTypeRegistry.fromFileName(path)); writeToResponse(in, response, request, requestGzipped); return response; diff --git a/common/src/main/resources/de/bluecolored/bluemap/config/webserver.conf b/common/src/main/resources/de/bluecolored/bluemap/config/webserver.conf index ad85f7fda..f3b60228a 100644 --- a/common/src/main/resources/de/bluecolored/bluemap/config/webserver.conf +++ b/common/src/main/resources/de/bluecolored/bluemap/config/webserver.conf @@ -34,7 +34,7 @@ log: { # Default is false (overwrite the file). append: false - # The format of the webserver acivity logs. + # The format of the webserver activity logs. # The syntax is the Java String formatting syntax, see: https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html # Possible Arguments: | Example output # 1 - the source address (ignoring any xff headers). | 10.10.10.10 @@ -47,3 +47,12 @@ log: { # Default is "%1$s \"%3$s %4$s %5$s\" %6$s %7$s" | 10.10.10.10 "GET /assets/file.png HTTP/1.1" 200 OK format: "%1$s \"%3$s %4$s %5$s\" %6$s %7$s" } + +# Additional headers to include in the responses for static files +additional-headers: { + # "Content-Security-Policy": "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; object-src 'none';" + "X-Frame-Options": "SAMEORIGIN" + "X-Content-Type-Options": "nosniff" + "Referrer-Policy": "strict-origin-when-cross-origin" + "Permissions-Policy": "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(self), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(self), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()" +} diff --git a/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java b/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java index e53cf54ba..fa1af8ac6 100644 --- a/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java +++ b/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java @@ -282,7 +282,7 @@ public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOExc RoutingRequestHandler routingRequestHandler = new RoutingRequestHandler(); // default route - routingRequestHandler.register(".*", new FileRequestHandler(config.getWebroot())); + routingRequestHandler.register(".*", new FileRequestHandler(config.getWebroot(), config.getAdditionalHeaders())); // map route for (var mapConfigEntry : blueMap.getConfig().getMapConfigs().entrySet()) { @@ -291,8 +291,8 @@ public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOExc BmMap map = blueMap.getMaps().get(mapConfigEntry.getKey()); MapRequestHandler mapRequestHandler = map != null ? - new MapRequestHandler(map, null, new LiveMarkersDataSupplier(map.getMarkerSets()), config.isSseEnabled()) : - new MapRequestHandler(storage); + new MapRequestHandler(map, null, new LiveMarkersDataSupplier(map.getMarkerSets()), config.isSseEnabled(), config.getAdditionalHeaders()) : + new MapRequestHandler(storage, config.getAdditionalHeaders()); routingRequestHandler.register( "maps/" + Pattern.quote(mapConfigEntry.getKey()) + "/(.*)", From 75a5864d419612cb65af32c8cac41cef67e3dc06 Mon Sep 17 00:00:00 2001 From: Ciaran Moran Date: Sun, 13 Sep 2026 21:35:21 +0100 Subject: [PATCH 2/3] Switch to BlueMapResponseModifier approach --- .../bluecolored/bluemap/common/plugin/Plugin.java | 14 ++++---------- .../common/web/BlueMapResponseModifier.java | 7 ++++++- .../bluemap/common/web/FileRequestHandler.java | 11 +---------- .../bluemap/common/web/MapRequestHandler.java | 14 ++++++-------- .../common/web/MapStorageRequestHandler.java | 14 -------------- .../bluemap/common/web/http/HttpHeaderCarrier.java | 4 ++++ .../de/bluecolored/bluemap/config/webserver.conf | 3 ++- .../de/bluecolored/bluemap/cli/BlueMapCLI.java | 10 +++++----- 8 files changed, 28 insertions(+), 49 deletions(-) diff --git a/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java b/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java index 95cc3cd96..4efcb2ee1 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java @@ -218,7 +218,7 @@ private void load(@Nullable ResourcePack preloadedResourcePack) throws IOExcepti this.webRequestHandler = new RoutingRequestHandler(); // default route - webRequestHandler.register(".*", new FileRequestHandler(webroot, webserverConfig.getAdditionalHeaders())); + webRequestHandler.register(".*", new BlueMapResponseModifier(new FileRequestHandler(webroot), webserverConfig.getAdditionalHeaders())); // map route for (var mapConfigEntry : configManager.getMapConfigs().entrySet()) { @@ -233,22 +233,16 @@ private void load(@Nullable ResourcePack preloadedResourcePack) throws IOExcepti null; LiveMarkersDataSupplier liveMarkersDataSupplier = new LiveMarkersDataSupplier(map.getMarkerSets()); - mapRequestHandler = new MapRequestHandler( - map, - livePlayersDataSupplier, - liveMarkersDataSupplier, - webserverConfig.isSseEnabled(), - webserverConfig.getAdditionalHeaders() - ); + mapRequestHandler = new MapRequestHandler(map, livePlayersDataSupplier, liveMarkersDataSupplier, webserverConfig.isSseEnabled()); } else { Storage storage = blueMap.getOrLoadStorage(mapConfig.getStorage()); - mapRequestHandler = new MapRequestHandler(storage.map(id), webserverConfig.getAdditionalHeaders()); + mapRequestHandler = new MapRequestHandler(storage.map(id)); } webRequestHandler.register( "maps/" + Pattern.quote(id) + "/(.*)", "$1", - new BlueMapResponseModifier(mapRequestHandler) + new BlueMapResponseModifier(mapRequestHandler, webserverConfig.getAdditionalHeaders()) ); } diff --git a/common/src/main/java/de/bluecolored/bluemap/common/web/BlueMapResponseModifier.java b/common/src/main/java/de/bluecolored/bluemap/common/web/BlueMapResponseModifier.java index 871938e1d..2f5da6801 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/web/BlueMapResponseModifier.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/web/BlueMapResponseModifier.java @@ -32,16 +32,19 @@ import lombok.Getter; import lombok.NonNull; import lombok.Setter; +import java.util.Map; @Getter @Setter public class BlueMapResponseModifier implements HttpRequestHandler { private @NonNull HttpRequestHandler delegate; private @NonNull String serverName; + private @NonNull Map additionalHeaders; - public BlueMapResponseModifier(HttpRequestHandler delegate) { + public BlueMapResponseModifier(HttpRequestHandler delegate, Map additionalHeaders) { this.delegate = delegate; this.serverName = "BlueMap/" + BlueMap.VERSION; + this.additionalHeaders = additionalHeaders; } @Override @@ -55,6 +58,8 @@ public HttpResponse handle(HttpRequest request) { response.addHeader("Server", this.serverName); + additionalHeaders.forEach(response::setHeader); + return response; } diff --git a/common/src/main/java/de/bluecolored/bluemap/common/web/FileRequestHandler.java b/common/src/main/java/de/bluecolored/bluemap/common/web/FileRequestHandler.java index 0809c8754..74db2e7fd 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/web/FileRequestHandler.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/web/FileRequestHandler.java @@ -26,7 +26,6 @@ import de.bluecolored.bluemap.common.web.http.*; import de.bluecolored.bluemap.core.logger.Logger; -import java.util.Map; import lombok.Getter; import lombok.NonNull; import lombok.Setter; @@ -46,11 +45,9 @@ public class FileRequestHandler implements HttpRequestHandler { private @NonNull Path webRoot; - private @NonNull Map additionalHeaders; - public FileRequestHandler(Path webRoot, Map additionalHeaders) { + public FileRequestHandler(Path webRoot) { this.webRoot = webRoot.normalize(); - this.additionalHeaders = additionalHeaders; } @Override @@ -139,12 +136,6 @@ private HttpResponse generateResponse(HttpRequest request) throws IOException { //create response HttpResponse response = new HttpResponse(HttpStatusCode.OK); - response.addHeader("Cache-Control", "public"); - response.addHeader("Cache-Control", "max-age=" + TimeUnit.DAYS.toSeconds(1)); - - additionalHeaders.forEach(response::addHeader); - - //headers after here will not be overwritten by additional headers from config response.addHeader("ETag", eTag); if (lastModified > 0) response.addHeader("Last-Modified", DateTimeFormatter.RFC_1123_DATE_TIME.format(Instant .ofEpochMilli(lastModified) diff --git a/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java b/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java index 1193cf953..2a04a794d 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java @@ -49,10 +49,9 @@ public MapRequestHandler( BmMap map, @Nullable Supplier livePlayersDataSupplier, @Nullable Supplier liveMarkerDataSupplier, - boolean useSSE, - Map additionalHeaders + boolean useSSE ) { - this(map.getStorage(), livePlayersDataSupplier, liveMarkerDataSupplier, useSSE, additionalHeaders); + this(map.getStorage(), livePlayersDataSupplier, liveMarkerDataSupplier, useSSE); if (useSSE) { map.getHiresModelManager().addTileUpdateListener(tile -> onTileUpdate(tile, 0)); @@ -60,18 +59,17 @@ public MapRequestHandler( } } - public MapRequestHandler(MapStorage mapStorage, Map additionalHeaders) { - this(mapStorage, null, null, false, additionalHeaders); + public MapRequestHandler(MapStorage mapStorage) { + this(mapStorage, null, null, false); } public MapRequestHandler( MapStorage mapStorage, @Nullable Supplier livePlayersDataSupplier, @Nullable Supplier liveMarkerDataSupplier, - boolean useSSE, - Map additionalHeaders + boolean useSSE ) { - register(".*", new MapStorageRequestHandler(mapStorage, additionalHeaders)); + register(".*", new MapStorageRequestHandler(mapStorage)); if (useSSE) { register("live/sse", "", _ -> { diff --git a/common/src/main/java/de/bluecolored/bluemap/common/web/MapStorageRequestHandler.java b/common/src/main/java/de/bluecolored/bluemap/common/web/MapStorageRequestHandler.java index bdc79e532..854a5e26c 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/web/MapStorageRequestHandler.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/web/MapStorageRequestHandler.java @@ -47,7 +47,6 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.Map; @RequiredArgsConstructor @Getter @Setter @@ -56,7 +55,6 @@ public class MapStorageRequestHandler implements HttpRequestHandler { private static final Pattern TILE_PATTERN = Pattern.compile("tiles/([\\d/]+)/x(-?[\\d/]+)z(-?[\\d/]+).*"); private @NonNull MapStorage mapStorage; - private @NonNull Map additionalHeaders; @Override public HttpResponse handle(HttpRequest request) { @@ -87,12 +85,6 @@ public HttpResponse handle(HttpRequest request) { if (in == null) return new HttpResponse(HttpStatusCode.NO_CONTENT); HttpResponse response = new HttpResponse(HttpStatusCode.OK); - response.addHeader("Cache-Control", "public"); - response.addHeader("Cache-Control", "max-age=" + TimeUnit.DAYS.toSeconds(1)); - - additionalHeaders.forEach(response::addHeader); - - //headers after here will not be overwritten by additional headers from config if (lod == 0) response.addHeader("Content-Type", "application/octet-stream"); else response.addHeader("Content-Type", "image/png"); @@ -110,12 +102,6 @@ public HttpResponse handle(HttpRequest request) { }; if (in != null){ HttpResponse response = new HttpResponse(HttpStatusCode.OK); - response.addHeader("Cache-Control", "public"); - response.addHeader("Cache-Control", "max-age=" + TimeUnit.DAYS.toSeconds(1)); - - additionalHeaders.forEach(response::addHeader); - - //headers after here will not be overwritten by additional headers from config response.addHeader("Content-Type", ContentTypeRegistry.fromFileName(path)); writeToResponse(in, response, request, requestGzipped); return response; diff --git a/common/src/main/java/de/bluecolored/bluemap/common/web/http/HttpHeaderCarrier.java b/common/src/main/java/de/bluecolored/bluemap/common/web/http/HttpHeaderCarrier.java index 5f7f8d45d..decabfd77 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/web/http/HttpHeaderCarrier.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/web/http/HttpHeaderCarrier.java @@ -35,6 +35,10 @@ default void addHeader(String name, String... values) { getHeaders().put(name.toLowerCase(Locale.ROOT), new HttpHeader(name, values)); } + default void setHeader(String name, String... values) { + getHeaders().put(name.toLowerCase(Locale.ROOT), new HttpHeader(name, values)); + } + default HttpHeader getHeader(String key) { return getHeaders().get(key.toLowerCase(Locale.ROOT)); } diff --git a/common/src/main/resources/de/bluecolored/bluemap/config/webserver.conf b/common/src/main/resources/de/bluecolored/bluemap/config/webserver.conf index f3b60228a..15970fd90 100644 --- a/common/src/main/resources/de/bluecolored/bluemap/config/webserver.conf +++ b/common/src/main/resources/de/bluecolored/bluemap/config/webserver.conf @@ -48,8 +48,9 @@ log: { format: "%1$s \"%3$s %4$s %5$s\" %6$s %7$s" } -# Additional headers to include in the responses for static files +# Additional headers to include in the responses for static files. additional-headers: { + "Cache-Control": "public, max-age=86400" # "Content-Security-Policy": "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; object-src 'none';" "X-Frame-Options": "SAMEORIGIN" "X-Content-Type-Options": "nosniff" diff --git a/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java b/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java index fa1af8ac6..cc66a4c9f 100644 --- a/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java +++ b/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java @@ -282,7 +282,7 @@ public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOExc RoutingRequestHandler routingRequestHandler = new RoutingRequestHandler(); // default route - routingRequestHandler.register(".*", new FileRequestHandler(config.getWebroot(), config.getAdditionalHeaders())); + routingRequestHandler.register(".*", new BlueMapResponseModifier(new FileRequestHandler(config.getWebroot()), config.getAdditionalHeaders())); // map route for (var mapConfigEntry : blueMap.getConfig().getMapConfigs().entrySet()) { @@ -291,13 +291,13 @@ public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOExc BmMap map = blueMap.getMaps().get(mapConfigEntry.getKey()); MapRequestHandler mapRequestHandler = map != null ? - new MapRequestHandler(map, null, new LiveMarkersDataSupplier(map.getMarkerSets()), config.isSseEnabled(), config.getAdditionalHeaders()) : - new MapRequestHandler(storage, config.getAdditionalHeaders()); + new MapRequestHandler(map, null, new LiveMarkersDataSupplier(map.getMarkerSets()), config.isSseEnabled()) : + new MapRequestHandler(storage); routingRequestHandler.register( "maps/" + Pattern.quote(mapConfigEntry.getKey()) + "/(.*)", "$1", - mapRequestHandler + new BlueMapResponseModifier(mapRequestHandler, config.getAdditionalHeaders()) ); } @@ -311,7 +311,7 @@ public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOExc )); } - HttpRequestHandler handler = new BlueMapResponseModifier(routingRequestHandler); + HttpRequestHandler handler = new BlueMapResponseModifier(routingRequestHandler, config.getAdditionalHeaders()); handler = new LoggingRequestHandler( handler, config.getLog().getFormat(), From 01351400637d1fac07ddee876ac28e0470deafb3 Mon Sep 17 00:00:00 2001 From: Ciaran Moran Date: Sun, 13 Sep 2026 22:31:10 +0100 Subject: [PATCH 3/3] Review comments --- .../de/bluecolored/bluemap/common/web/MapRequestHandler.java | 2 -- .../src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java b/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java index 2a04a794d..18acf60ff 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/web/MapRequestHandler.java @@ -28,13 +28,11 @@ import de.bluecolored.bluemap.common.web.http.HttpStatusCode; import de.bluecolored.bluemap.core.map.BmMap; import de.bluecolored.bluemap.core.storage.MapStorage; -import java.util.Map; import org.jetbrains.annotations.Nullable; import com.flowpowered.math.vector.Vector2i; import java.io.Closeable; -import java.io.IOException; import java.util.function.Consumer; import java.util.function.Supplier; diff --git a/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java b/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java index cc66a4c9f..a480562d9 100644 --- a/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java +++ b/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java @@ -282,7 +282,7 @@ public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOExc RoutingRequestHandler routingRequestHandler = new RoutingRequestHandler(); // default route - routingRequestHandler.register(".*", new BlueMapResponseModifier(new FileRequestHandler(config.getWebroot()), config.getAdditionalHeaders())); + routingRequestHandler.register(".*", new FileRequestHandler(config.getWebroot())); // map route for (var mapConfigEntry : blueMap.getConfig().getMapConfigs().entrySet()) { @@ -297,7 +297,7 @@ public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOExc routingRequestHandler.register( "maps/" + Pattern.quote(mapConfigEntry.getKey()) + "/(.*)", "$1", - new BlueMapResponseModifier(mapRequestHandler, config.getAdditionalHeaders()) + mapRequestHandler ); }