CORS настройки

CORS (Cross-Origin Resource Sharing) в контексте Mapbox GL JS определяет правила, по которым браузер разрешает или блокирует загрузку географических ресурсов (тайлов, шрифтов, изображений, спрайтов) с доменов, отличных от домена текущего приложения. В веб-картографии это критический механизм, поскольку практически все данные — векторные тайлы, растровые слои, стили и шрифты — часто приходят с удалённых серверов.

В Mapbox GL JS рендеринг выполняется через WebGL, а это накладывает дополнительные ограничения: любая текстура, загруженная с другого источника без корректных CORS-заголовков, может привести к блокировке отрисовки или «tainted canvas», что делает невозможным использование карты для экспорта изображений или постобработки.


Mapbox GL JS опирается на несколько типов удалённых ресурсов:

  • векторные тайлы (vector tiles)
  • растровые тайлы (raster tiles)
  • стили (style JSON)
  • шрифты (glyphs)
  • спрайты (sprite images + JSON)
  • изображения пользовательских источников
  • GeoJSON через HTTP(S)
  • видео и image sources (в специфических случаях)

Каждый из этих типов загружается через стандартный сетевой стек браузера, а значит подчиняется CORS-политике.

Ключевой момент заключается в том, что Mapbox GL JS не обходит CORS-ограничения — он полностью зависит от корректной конфигурации HTTP-ответов сервера.


Базовые требования CORS для картографических ресурсов

Для успешной загрузки ресурсов сервер должен возвращать заголовки:

Access-Control-Allow-Origin: *

или более строго:

Access-Control-Allow-Origin: https://example.com

Дополнительно могут требоваться:

Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Content-Type

Для ресурсов, использующих кэширование и предварительные запросы, важно корректно обрабатывать OPTIONS preflight.


Mapbox и встроенная CORS-совместимость

Сервисы Mapbox (tiles, styles, sprites, glyphs) уже настроены на корректную работу с CORS. Это означает:

  • ответы содержат Access-Control-Allow-Origin: *
  • изображения и тайлы могут использоваться как WebGL textures
  • отсутствуют ограничения на cross-origin загрузку при стандартном использовании access token

Это делает интеграцию прозрачной при использовании официальных источников данных.


Проблема пользовательских тайл-серверов

При подключении собственных серверов тайлов возникают типичные ограничения. Например:

  • Nginx или Apache по умолчанию не добавляют CORS-заголовки
  • S3 bucket без CORS-конфигурации блокирует загрузку
  • сторонние tile providers могут отдавать данные без поддержки cross-origin

В результате возникают ошибки:

No 'Access-Control-Allow-Origin' header is present on the requested resource

или

Blocked by CORS policy: Response to preflight request doesn't pass access control check

WebGL и «tainted canvas»

Mapbox GL JS использует WebGL для отрисовки. Это создаёт дополнительное ограничение:

  • если хотя бы один ресурс загружен без CORS — canvas становится «tainted»
  • экспорт карты через map.getCanvas().toDataURL() перестаёт работать
  • любые операции чтения пикселей блокируются браузером

Даже если визуально карта отображается корректно, отсутствие CORS может проявиться только при попытке экспорта.


transformRequest как основной механизм управления CORS

В Mapbox GL JS ключевым инструментом контроля сетевых запросов является transformRequest.

Он позволяет перехватывать все запросы к ресурсам и модифицировать их:

  • добавлять заголовки
  • менять URL
  • переключать источники
  • проксировать запросы
  • управлять credentials mode

Пример базовой конфигурации:

const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v12',
  transformRequest: (url, resourceType) => {
    return {
      url,
      headers: resourceType === 'Tile' ? { 'X-Custom-Header': 'value' } : {}
    };
  }
});

Управление cross-origin режимом загрузки

Для ресурсов изображений браузер использует механизм crossOrigin. В контексте Mapbox GL JS это критично для:

  • image sources
  • icon images
  • sprites
  • raster layers

Типовые значения:

  • anonymous — загрузка без cookies
  • use-credentials — с cookies (требует строгой настройки сервера)

При неправильной настройке даже корректные CORS-заголовки могут не помочь, если режим загрузки не совпадает.


Векторные тайлы и CORS

Векторные тайлы особенно чувствительны к CORS, поскольку:

  • они декодируются в GPU буферы
  • участвуют в генерации WebGL buffers
  • часто загружаются большими пачками

Если сервер тайлов не поддерживает CORS:

  • слои не отображаются
  • консоль содержит ошибки загрузки
  • карта может частично отрисовываться (fallback behavior)

Растровые тайлы и ограничения браузера

Растровые тайлы загружаются как изображения (img элементы). Для них CORS важен в контексте:

  • использования как WebGL texture
  • применения opacity и compositing
  • постобработки через canvas

Без корректного CORS изображения становятся «opaque» и теряют доступность для GPU-операций.


Glyphs и шрифты

Шрифты в Mapbox GL JS загружаются в формате PBF через endpoint glyphs.

Если CORS настроен неправильно:

  • текст не отображается
  • fallback шрифты не применяются корректно
  • появляются пустые подписи слоёв

Важно, что glyphs часто кэшируются агрессивно, и ошибки могут сохраняться даже после исправления сервера.


Спрайты и их двойная структура

Спрайты состоят из:

  • JSON (описание координат иконок)
  • PNG (или WebP) изображения

Оба ресурса обязаны иметь одинаковую CORS-политику.

Несовпадение приводит к ситуации:

  • JSON загружается
  • изображение блокируется
  • иконки отображаются как пустые квадраты

GeoJSON и CORS

GeoJSON-источники также подчиняются CORS, если загружаются по URL:

source: {
  type: 'geojson',
  data: 'https://example.com/data.geojson'
}

Если сервер не возвращает CORS-заголовки:

  • данные не загружаются
  • слой остаётся пустым
  • консоль фиксирует network error

Прокси как универсальное решение

При невозможности изменить сервер применяется проксирование:

  • backend прокси (Node.js, Nginx)
  • serverless functions
  • edge workers

Пример логики прокси:

Browser → same-origin proxy → tile server

Преимущества:

  • обход CORS без изменения внешнего сервера
  • возможность добавления авторизации
  • централизованный контроль кеширования

Недостатки:

  • дополнительная задержка
  • нагрузка на инфраструктуру
  • необходимость поддержки потоковой передачи больших тайлов

OPTIONS preflight и его влияние на производительность

При сложных запросах браузер выполняет preflight:

OPTIONS /tile/12/1200/1530.pbf

Если сервер не отвечает корректно:

  • запрос блокируется до получения таймаута
  • карта загружается частично или с задержкой
  • увеличивается Time to Interactive

Оптимизация включает:

  • корректную обработку OPTIONS
  • минимизацию кастомных заголовков
  • использование простых GET-запросов

Частые ошибки CORS в Mapbox GL JS

Типовые сценарии проблем:

  1. Отсутствие Access-Control-Allow-Origin
  2. Несоответствие протоколов (http vs https)
  3. Блокировка mixed content
  4. Неверный credentials mode
  5. Несовпадение sprite/glyph доменов
  6. CDN без CORS headers

Каждая из этих проблем может проявляться не сразу, а только при определённых масштабах или уровнях зума.


Конфигурационные паттерны для стабильной работы

Устойчивые архитектуры обычно включают:

  • единый домен для всех tile endpoints
  • CDN с включённым CORS
  • централизованный transformRequest
  • прокси слой для legacy источников
  • строгую унификацию https

Типовой подход:

transformRequest: (url, resourceType) => {
  if (url.startsWith('http://legacy-tiles.com')) {
    return {
      url: `/proxy?url=${encodeURIComponent(url)}`
    };
  }
  return { url };
}

Влияние CORS на производительность рендеринга

CORS влияет не только на доступность, но и на скорость:

  • preflight увеличивает latency
  • повторные запросы блокируются кэшем иначе
  • ошибки приводят к повторным попыткам загрузки
  • WebGL ожидание текстур замедляет frame rendering

Оптимальная конфигурация минимизирует cross-origin запросы в критическом пути рендеринга тайлов.