The following has been put up on OSM how do we get this into Gramps any ideas welcome
Just tested, it finally works again with X-Requested-With.
For some time it did work first (when i posted the Error 403 when using local files - referer missing - can I use User Agent and what should it contain - #46 by Spiekerooger - Help and support - OpenStreetMap Community Forum solution) and then did not work as the OPTIONS preflight request did not work anymore but that changed again and now it is working again.
So here is an example for a working local (file://) leaflet page that is able to request tiles via FF by using the extra X-Requested-With header:
<!DOCTYPE html>
<html lang="en">
<head>
<base target="_top">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Quick Start - Leaflet</title>
<link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<style>
html, body {
height: 100%;
margin: 0;
}
.leaflet-container {
height: 400px;
width: 600px;
max-width: 100%;
max-height: 100%;
}
</style>
</head>
<body>
<div id="map" style="width: 600px; height: 400px;"></div>
<script>
'use strict';
async function fetchImage(url, callback, headers, abort) {
let _headers = {};
if (headers) {
headers.forEach(h => {
_headers[h.header] = h.value;
});
}
const controller = new AbortController();
const signal = controller.signal;
if (abort) {
abort.subscribe(() => {
controller.abort();
});
}
const f = await fetch(url, {
method: "GET",
headers: _headers,
mode: "cors",
signal: signal
});
const blob = await f.blob();
callback(blob);
}
L.TileLayerWithHeaders = L.TileLayer.extend({
initialize: function (url, options, headers, abort) {
L.TileLayer.prototype.initialize.call(this, url, options);
this.headers = headers;
this.abort = abort;
},
createTile(coords, done) {
const url = this.getTileUrl(coords);
const img = document.createElement("img");
img.setAttribute("role", "presentation");
fetchImage(
url,
resp => {
const reader = new FileReader();
reader.onload = () => {
img.src = reader.result;
};
reader.readAsDataURL(resp);
done(null, img);
},
this.headers,
this.abort
);
return img;
}
});
L.tileLayer = function (url, options, headers, abort) {
return new L.TileLayerWithHeaders(url, options, headers, abort);
};
const map = L.map('map').setView([51.505, -0.09], 13);
const tiles = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
},
[
{ header: 'X-Requested-With', value: 'my-fancy-app-called-via-file' }
],
null
).addTo(map);
const marker = L.marker([51.5, -0.09]).addTo(map)
.bindPopup('<b>Hello world!</b><br />I am a popup.').openPopup();
const circle = L.circle([51.508, -0.11], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 500
}).addTo(map).bindPopup('I am a circle.');
const polygon = L.polygon([
[51.509, -0.08],
[51.503, -0.06],
[51.51, -0.047]
]).addTo(map).bindPopup('I am a polygon.');
const popup = L.popup()
.setLatLng([51.513, -0.09])
.setContent('I am a standalone popup.')
.openOn(map);
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent(`You clicked the map at ${e.latlng.toString()}`)
.openOn(map);
}
map.on('click', onMapClick);
</script>
</body>
</html>
Just copy and paste that into a local html file and test by opening it as a file://…