CORS настройки

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

Kepler.gl сам по себе не реализует обход CORS — он наследует ограничения браузера и использует стандартный стек загрузки данных (fetch, XHR, loaders.gl). Поэтому корректная работа с внешними источниками данных напрямую зависит от конфигурации серверов и способа интеграции данных.


Архитектура загрузки данных и точки возникновения CORS

Kepler.gl использует связку:

  • kepler.gl (UI слой)
  • deck.gl (рендеринг слоёв WebGL)
  • loaders.gl (загрузка и парсинг данных)

Именно loaders.gl выполняет сетевые запросы к:

  • CSV / JSON / GeoJSON
  • Mapbox Vector Tiles (MVT)
  • Raster tiles
  • Image sources
  • Remote APIs

Каждый запрос из браузера проходит через fetch() или XHR, а значит подчиняется CORS-ограничениям.

Типовая цепочка:

  1. Пользователь добавляет URL источника данных
  2. Kepler.gl передаёт URL в loaders.gl
  3. loaders.gl вызывает fetch
  4. Браузер проверяет CORS-заголовки ответа
  5. При отсутствии разрешения запрос блокируется

Основные сценарии возникновения CORS ошибок

1. Загрузка CSV/GeoJSON с удалённого сервера

Типичная ошибка:

Access to fetch at 'https://api.example.com/data.csv' from origin 'http://localhost:3000'
has been blocked by CORS policy

Причина — сервер не возвращает:

Access-Control-Allow-Origin: *

или конкретный origin приложения.


2. Подключение Mapbox стилей и тайлов

Kepler.gl активно использует Mapbox Style Specification. При загрузке:

  • style.json
  • raster tiles
  • vector tiles

возникают дополнительные CORS-запросы к CDN Mapbox или кастомным тайловым серверам.

Особенно часто блокируются:

  • *.tiles.mapbox.com
  • кастомные tile servers без CORS headers

3. Локальные файлы и file:// протокол

При попытке загрузки локального JSON/CSV напрямую:

  • браузер блокирует запросы
  • origin становится null

Kepler.gl решает это через загрузку файлов в память (drag & drop), но URL-подгрузка всё равно требует HTTP(S).


Настройки Kepler.gl, влияющие на CORS

Хотя Kepler.gl не управляет CORS напрямую, ряд параметров влияет на поведение загрузки данных:

dataUrl

Используется для передачи удалённого источника:

addDataToMap({
  datasets: {
    info: { label: 'remote data' },
    data: null,
    url: 'https://example.com/data.geojson'
  }
});

Если URL cross-origin, ответственность за CORS лежит на сервере.


loaders конфигурация

Kepler.gl позволяет прокидывать кастомные loaders:

import { load } from '@loaders.gl/core';

load(url, CSVLoader, {
  fetch: {
    mode: 'cors'
  }
});

Параметр mode: 'cors' не решает проблему сам по себе, но определяет режим запроса.


MapStyle и кастомные тайлы

При использовании кастомного style JSON:

mapStyle: {
  styleType: 'custom',
  style: 'https://myserver.com/style.json'
}

Все ресурсы внутри style.json также должны поддерживать CORS:

  • sprites
  • glyphs
  • tiles

Конфигурация серверов для устранения CORS

Express.js

Базовая настройка:

import cors from 'cors';
import express from 'express';

const app = express();

app.use(cors({
  origin: '*'
}));

Для более строгой политики:

app.use(cors({
  origin: 'https://my-kepler-app.com'
}));

Nginx

location /data/ {
  add_header Access-Control-Allow-Origin *;
  add_header Access-Control-Allow-Methods "GET, OPTIONS";
}

Для preflight-запросов:

if ($request_method = OPTIONS ) {
  add_header Access-Control-Allow-Origin *;
  add_header Access-Control-Allow-Methods "GET, OPTIONS";
  return 204;
}

S3 / Cloud Storage

Для AWS S3 необходимо CORS-конфигурация бакета:

[
  {
    "AllowedOrigins": ["*"],
    "AllowedMethods": ["GET"],
    "AllowedHeaders": ["*"]
  }
]

Без этого Kepler.gl не сможет загружать GeoJSON/CSV напрямую из bucket URL.


Прокси-стратегия как универсальное решение

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

Простой proxy на Node.js

app.get('/proxy', async (req, res) => {
  const url = req.query.url;

  const response = await fetch(url);
  const data = await response.text();

  res.setHeader('Access-Control-Allow-Origin', '*');
  res.send(data);
});

Kepler.gl получает уже “локальный” URL:

/proxy?url=https://external-site.com/data.csv

Reverse proxy (Nginx)

location /proxy/ {
  proxy_pass https://external-site.com/;
}

Mapbox и CORS в Kepler.gl

Mapbox является частым источником CORS-конфликтов:

  • стили
  • тайлы
  • шрифты (glyphs)

Обязательные условия:

  • корректный access_token
  • публичный доступ к style URL
  • разрешённые origins в Mapbox account settings

Некорректная конфигурация приводит к:

  • белой карте
  • отсутствию слоёв
  • ошибкам загрузки tiles.json

CORS и loaders.gl: технические детали

loaders.gl использует расширенный fetch-слой:

  • поддержка RequestInit
  • управление credentials
  • обработка Response

Пример:

load(url, GeoJSONLoader, {
  fetch: {
    credentials: 'omit'
  }
});

Значение credentials:

  • omit — без cookies (рекомендуется)
  • include — с cookies (часто ломает CORS)
  • same-origin — только для того же домена

Частые ошибки конфигурации

1. credentials + wildcard origin

Нельзя использовать одновременно:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

2. Redirects без CORS headers

Если URL редиректится (301/302), конечный сервер тоже должен отдавать CORS-заголовки.


3. CDN без preflight поддержки

Некоторые CDN блокируют OPTIONS-запросы, что ломает POST/complex requests.


Диагностика CORS проблем в Kepler.gl

1. DevTools Network

Проверяются:

  • Response headers
  • OPTIONS запросы
  • статус 200/403/blocked

2. Console ошибки

Типичные сообщения:

  • blocked by CORS policy
  • No ‘Access-Control-Allow-Origin’
  • preflight response is not successful

3. Проверка loaders.gl

Можно перехватывать загрузку:

import { setLoaderOptions } from '@loaders.gl/core';

setLoaderOptions({
  fetch: (url, options) => {
    console.log('loading:', url);
    return fetch(url, options);
  }
});

Безопасностные аспекты CORS в Kepler.gl

CORS не является механизмом защиты данных, а лишь ограничением браузера.

Важно учитывать:

  • открытый * допустим только для публичных данных
  • приватные датасеты требуют авторизации через API gateway
  • Kepler.gl не шифрует и не скрывает источники данных

Практика построения устойчивой архитектуры загрузки данных

Для стабильной работы Kepler.gl в продакшене обычно используется:

  • единый data gateway
  • прокси-слой
  • стандартизированные headers
  • CDN с корректным CORS
  • Mapbox/tiles сервер с whitelist origin

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