Skip to content

Commit a1bbe85

Browse files
paul43210claude
andcommitted
fix(photo-addon): add referrer policy for OSM map tiles
OSM's tile servers require a Referer header, but oCIS may set a strict Referrer-Policy that strips it, causing intermittent 403 errors on map tiles. Fix: inject a meta referrer tag and set referrerPolicy on each tile image element. Failed tiles retry once after 500ms. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 324b719 commit a1bbe85

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

packages/web-app-photo-addon/src/components/PhotoMap.vue

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,36 @@ function initMap() {
473473
prefetchVisibleClusters()
474474
})
475475
476-
// Add OpenStreetMap tile layer (noWrap prevents world map repeating)
477-
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
476+
// OSM tile servers require a Referer header. Ensure referrer policy allows it.
477+
let metaReferrer = document.querySelector('meta[name="referrer"]') as HTMLMetaElement | null
478+
if (!metaReferrer) {
479+
metaReferrer = document.createElement('meta')
480+
metaReferrer.name = 'referrer'
481+
metaReferrer.content = 'no-referrer-when-downgrade'
482+
document.head.appendChild(metaReferrer)
483+
} else if (metaReferrer.content === 'no-referrer' || metaReferrer.content === 'same-origin') {
484+
// Temporarily relax for OSM tiles — restored on unmount
485+
metaReferrer.dataset.originalContent = metaReferrer.content
486+
metaReferrer.content = 'no-referrer-when-downgrade'
487+
}
488+
489+
// Tile layer with retry on 403 (transient referrer issues)
490+
const OsmTileLayer = L.TileLayer.extend({
491+
createTile(coords: any, done: any) {
492+
const tile = L.TileLayer.prototype.createTile.call(this, coords, done) as HTMLImageElement
493+
tile.referrerPolicy = 'no-referrer-when-downgrade'
494+
const originalSrc = tile.src
495+
tile.addEventListener('error', () => {
496+
// Retry once after a short delay
497+
if (!tile.dataset.retried) {
498+
tile.dataset.retried = '1'
499+
setTimeout(() => { tile.src = originalSrc }, 500)
500+
}
501+
}, { once: false })
502+
return tile
503+
}
504+
})
505+
new OsmTileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
478506
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
479507
maxZoom: 19,
480508
keepBuffer: 2,
@@ -780,6 +808,12 @@ onUnmounted(() => {
780808
activeTooltip.remove()
781809
activeTooltip = null
782810
}
811+
// Restore original referrer policy if we changed it
812+
const metaRef = document.querySelector('meta[name="referrer"]') as HTMLMetaElement | null
813+
if (metaRef?.dataset.originalContent) {
814+
metaRef.content = metaRef.dataset.originalContent
815+
delete metaRef.dataset.originalContent
816+
}
783817
// Clean up injected CSS (only if no other PhotoMap instances)
784818
// Note: We leave the CSS in place since it's idempotent and shared
785819
// Removing it could break other instances if multiple PhotoMaps exist

0 commit comments

Comments
 (0)