Local CORS proxy: nginx forwards /carto/ to a.basemaps.cartocdn.com
Direct fetching from a.basemaps.cartocdn.com was returning stripped/missing CORS headers in the user's browser, blocking the img.src load. Even with cache-busters the failure persisted. Solution: local nginx proxy at /carto/ that forwards to the upstream and always adds Access-Control-Allow-Origin: *. Key detail: the 'resolver' directive is required inside the proxy_pass location block so nginx can resolve the upstream hostname. Without it, the location block silently fails (the '/' location falls through to try_files ... =404, and the ~*\.(png|jpg)$ regex also matches and silently fails for GETs). Also added 'location ^~ /carto/' to give prefix matching strict priority over the .png regex match that was stealing the request. JS now uses /carto/voyager/ (relative URL through the same origin) so CORS preflight is not even needed.
This commit is contained in:
1 parent
83fd829cd5
commit
f55d96f462
2 files changed
+31
-7
No files matched your search
+28
-1
@@ -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;
|
||||
}
|
||||
|
||||
# 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;
|
||||
}
|
||||
}
|
||||
Vendored
+3
-6
@@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user