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..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)); + webRequestHandler.register(".*", new BlueMapResponseModifier(new FileRequestHandler(webroot), webserverConfig.getAdditionalHeaders())); // map route for (var mapConfigEntry : configManager.getMapConfigs().entrySet()) { @@ -242,7 +242,7 @@ private void load(@Nullable ResourcePack preloadedResourcePack) throws IOExcepti 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 0aaa86cbd..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 @@ -135,13 +135,12 @@ private HttpResponse generateResponse(HttpRequest request) throws IOException { //create response HttpResponse response = new HttpResponse(HttpStatusCode.OK); + 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..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 @@ -33,7 +33,6 @@ 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/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..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 @@ -85,9 +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)); - if (lod == 0) response.addHeader("Content-Type", "application/octet-stream"); else response.addHeader("Content-Type", "image/png"); @@ -105,8 +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)); 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 ad85f7fda..15970fd90 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,13 @@ 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: { + "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" + "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..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 @@ -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(),