CORS и работа с внешними источниками

В браузерной среде любые запросы к внешним источникам данных подчиняются политике одинакового источника (Same-Origin Policy). При работе с веб-картами это становится критическим фактором, поскольку карты почти всегда состоят из множества внешних ресурсов: тайловых серверов, векторных API, WMS/WFS сервисов, шрифтов, изображений и данных пространственных слоёв.

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

Особенности загрузки внешних ресурсов в OpenLayers

OpenLayers активно использует браузерные механизмы загрузки ресурсов через XMLHttpRequest, fetch и <img> элементы. В зависимости от типа слоя применяются разные стратегии:

  • растровые тайлы (ol/source/XYZ, ol/source/TileWMS)
  • изображения (ol/source/ImageWMS)
  • векторные данные (ol/source/Vector, ol/format/GeoJSON, ol/format/WFS)
  • тайловые векторные источники (ol/source/VectorTile)

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

Растровые тайлы и CORS

Тайловые слои являются наиболее чувствительными к настройкам кросс-доменных запросов. При использовании ol/source/XYZ или аналогичных источников браузер загружает изображения через <img>.

Поведение без CORS

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

Access-Control-Allow-Origin: *

или конкретный домен, возникают ограничения:

  • невозможность использовать canvas-операции (например, постобработку тайлов)
  • блокировка при попытке чтения пикселей (getImageData)
  • потенциальные ошибки при экспорте карты в изображение

Поведение с включённым CORS

При корректной настройке:

  • тайлы загружаются без ограничений
  • допускается использование canvas-композиции
  • возможен экспорт карты в PNG/JPEG

Ключевая настройка OpenLayers:

new ol.source.XYZ({
  url: 'https://tile.server/{z}/{x}/{y}.png',
  crossOrigin: 'anonymous'
})

Параметр crossOrigin критически важен: он заставляет браузер выполнять запрос как CORS-запрос, а не как «непрозрачную» загрузку изображения.

ImageWMS и серверные ограничения

WMS-сервисы часто используются для динамических картографических изображений. В OpenLayers они реализуются через ol/source/ImageWMS.

Особенность заключается в том, что каждый запрос формирует изображение на сервере, а не получает готовый тайл.

new ol.source.ImageWMS({
  url: 'https://gis.server/wms',
  params: { LAYERS: 'roads' },
  crossOrigin: 'anonymous'
})

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

  • изображение не будет отображено
  • canvas станет «tainted»
  • невозможно выполнить пиксельный анализ

В некоторых GIS-серверах (GeoServer, MapServer) требуется явная настройка CORS-фильтра.

Векторные данные и XHR-запросы

Векторные источники используют fetch или XMLHttpRequest, поэтому CORS становится обязательным условием.

Пример GeoJSON:

new ol.source.Vector({
  url: 'https://api.server/data.geojson',
  format: new ol.format.GeoJSON(),
  crossOrigin: 'anonymous'
})

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

  • данные полностью блокируются браузером
  • ошибка появляется в консоли (CORS policy error)
  • слой остаётся пустым

Типичные заголовки сервера

Для корректной работы:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: Content-Type

WFS и сложные запросы

WFS (Web Feature Service) чаще использует POST-запросы, что усложняет CORS-конфигурацию.

При работе с фильтрами (OGC Filter Encoding):

  • браузер отправляет preflight OPTIONS-запрос
  • сервер обязан корректно отвечать на OPTIONS
  • требуется поддержка Access-Control-Allow-Headers

Отсутствие поддержки preflight приводит к полной недоступности слоя, даже если GET-запросы разрешены.

TileJSON, WMTS и промежуточные API

Некоторые источники используют промежуточные описательные форматы:

  • TileJSON
  • WMTS capabilities
  • custom REST tile APIs

Для них характерны дополнительные проблемы:

  • множественные домены (CDN + API)
  • редиректы между сервисами
  • смешанный контент (HTTP/HTTPS)

OpenLayers не обходит CORS-ограничения, поэтому вся цепочка запросов должна быть разрешена сервером.

Проблема canvas tainting

Одним из наиболее критичных эффектов CORS является «загрязнение canvas».

Если хотя бы один слой загружен без CORS, запрещаются операции:

  • toDataURL()
  • getImageData()
  • экспорт карты

Даже один некорректный тайл может сделать весь canvas недоступным для экспорта.

Прокси как решение ограничений

При отсутствии возможности изменить сервер применяется сервер-прокси.

Схема:

OpenLayers → прокси → внешний GIS сервер

Прокси добавляет нужные заголовки:

Access-Control-Allow-Origin: *

и преобразует запросы.

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

  • принимает URL от клиента
  • выполняет запрос на GIS сервер
  • возвращает ответ с добавленными CORS-заголовками

Это особенно актуально для:

  • закрытых WMS-сервисов
  • корпоративных GIS систем
  • устаревших серверов без CORS поддержки

Кросс-доменные тайлы и CDN

При использовании CDN часто возникает распределённая архитектура:

  • основной API домен
  • домен тайлов
  • домен статики

Для корректной работы требуется единая политика CORS между всеми доменами.

Типичные ошибки:

  • тайлы загружаются, но canvas блокируется
  • часть слоёв отображается, часть — нет
  • нестабильное поведение при масштабировании

Безопасность и ограничения wildcard

Использование:

Access-Control-Allow-Origin: *

имеет ограничения:

  • запрещено при использовании credentials
  • несовместимо с cookie-аутентификацией
  • может быть заблокировано корпоративными политиками

Альтернатива:

Access-Control-Allow-Origin: https://app.domain.com

В GIS-системах часто используется whitelist доменов.

CrossOrigin в OpenLayers как ключевой параметр

Практически все источники OpenLayers поддерживают параметр:

crossOrigin: 'anonymous'

Возможные значения:

  • anonymous — стандартный CORS-запрос без cookies
  • use-credentials — с передачей учётных данных
  • null — отключение CORS-режима

Неправильный выбор значения приводит к:

  • блокировке запросов
  • невозможности рендеринга слоёв
  • ошибкам canvas безопасности

Частые ошибки при интеграции внешних GIS источников

Ошибка 1: отсутствие OPTIONS обработки

Preflight-запросы не обрабатываются сервером.

Ошибка 2: смешанный контент

HTTPS-карта обращается к HTTP-сервису.

Ошибка 3: отсутствие заголовков на тайлах

Заголовки есть на API, но отсутствуют на изображениях.

Ошибка 4: редиректы между доменами

CORS-заголовки теряются при 302/301 редиректах.

Ошибка 5: использование canvas без crossOrigin

Даже при корректном сервере canvas становится недоступным.

Стратегии диагностики CORS-проблем

Основные признаки:

  • пустые слои без ошибок в UI
  • сообщения в консоли браузера
  • частичная загрузка тайлов
  • блокировка экспорта карты

Методы анализа:

  • проверка Network tab
  • анализ response headers
  • тест прямого доступа к URL
  • проверка preflight OPTIONS

Особенности работы с векторными тайлами

VectorTile источники используют бинарные форматы (PBF), которые особенно чувствительны к CORS.

new ol.source.VectorTile({
  url: 'https://tiles.server/{z}/{x}/{y}.pbf',
  format: new ol.format.MVT(),
  crossOrigin: 'anonymous'
})

Без CORS:

  • невозможна декодировка данных
  • слой не рендерится
  • отсутствует геометрия на карте

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

Некорректная настройка может приводить к:

  • повторным запросам тайлов
  • увеличению latency из-за preflight
  • блокировке кеширования
  • деградации рендеринга при панорамировании

Правильная CORS-конфигурация позволяет:

  • использовать HTTP cache
  • снижать нагрузку на сервер
  • ускорять тайловую загрузку
  • стабилизировать отрисовку слоёв