diff --git a/default.conf b/default.conf index 9f2635a..0129b77 100644 --- a/default.conf +++ b/default.conf @@ -1,10 +1,37 @@ server { listen 58881 default_server; - server_name localhost; + server_name localhost _; root /usr/share/nginx/html; index background.html; location / { try_files $uri $uri/ =404; } -} \ No newline at end of file + + # CORS proxy for map tiles. Forwards to the upstream tile server + # but injects permissive CORS headers so the browser can load + # tiles via cross-origin img.src requests. The 'resolver' is + # required by the proxy module to resolve the upstream hostname. + location ^~ /carto/ { + resolver 1.1.1.1 8.8.8.8 ipv6=off valid=300s; + proxy_pass https://a.basemaps.cartocdn.com/; + proxy_ssl_server_name on; + proxy_set_header Host a.basemaps.cartocdn.com; + proxy_set_header User-Agent "Mozilla/5.0 (compatible; tile-proxy)"; + add_header Access-Control-Allow-Origin "*" always; + add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always; + add_header Access-Control-Max-Age 86400 always; + } + + # CORS preflight handler + location ~* \.(png|jpg)$ { + if ($request_method = 'OPTIONS') { + add_header Access-Control-Allow-Origin "*" always; + add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always; + add_header Access-Control-Max-Age 86400 always; + add_header Content-Length 0; + return 204; + } + add_header Access-Control-Allow-Origin "*" always; + } +} diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index 7506955..9b4c28c 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -284,7 +284,7 @@ function init(canvas) { // mosaic centre always corresponds to UV (0.5, 0.5). // Tile source: Carto basemaps Voyager style (with place names). // Free, CORS-enabled, OSM-derived. URL format {z}/{x}/{y}.png. -var GROUND_TILE_URL = 'https://a.basemaps.cartocdn.com/voyager/'; +var GROUND_TILE_URL = '/carto/voyager/'; var GROUND_TILE_Z = 11; var GROUND_TILE_SIZE = 256; // Fetch direction: which way the tile corridor is oriented. @@ -318,11 +318,8 @@ function fetchTileImage(tileX, tileY) { img.crossOrigin = 'anonymous'; img.onload = function() { resolve(img); }; img.onerror = function() { reject(new Error('tile fetch failed')); }; - // Carto/OSM-style format: {z}/{x}/{y}.png with a per-tile cache - // buster to avoid any browser-cached 404s or CORS rejections - // from previous failed loads. - img.src = GROUND_TILE_URL + GROUND_TILE_Z + '/' + tileX + '/' + tileY - + '?v=' + Date.now() + '_' + Math.floor(Math.random() * 1e6); + // Carto/OSM-style format: {z}/{x}/{y}.png via local proxy + img.src = GROUND_TILE_URL + GROUND_TILE_Z + '/' + tileX + '/' + tileY; }); }