В веб-картографии основная проблема загрузки данных из внешних источников связана с политикой CORS (Cross-Origin Resource Sharing). Браузер ограничивает доступ к ресурсам, если они находятся на другом домене и не содержат корректных заголовков разрешения.
В CesiumJS это проявляется особенно часто, поскольку визуализация сцены опирается на множество удалённых сервисов:
При отсутствии корректной CORS-конфигурации запросы блокируются браузером. Прокси-сервер становится промежуточным слоем, который выполняет запросы от имени клиента и возвращает данные с добавлением необходимых заголовков.
Прокси в контексте CesiumJS выступает как промежуточный HTTP/HTTPS шлюз между клиентским приложением и источниками геоданных.
Типовая схема:
CesiumJS (браузер)
↓
Proxy сервер (Node.js / Nginx / Backend)
↓
WMS / WMTS / Tile server / Cesium ion / API
Функции такого слоя:
CesiumJS предоставляет встроенную абстракцию прокси через
Proxy и связанные механизмы Resource.
Основные точки интеграции:
Cesium использует абстракцию:
new Cesium.DefaultProxy(proxyUrl);
или кастомную реализацию:
class MyProxy {
getURL(resource) {
return `/proxy?url=${encodeURIComponent(resource)}`;
}
}
Любой объект, реализующий метод преобразования URL, может использоваться как прокси.
Cesium.Resource — базовый механизм загрузки данных.
const resource = new Cesium.Resource({
url: "https://example.com/tiles/{z}/{x}/{y}.png",
proxy: new Cesium.DefaultProxy("/proxy/")
});
При таком подходе все запросы будут проходить через заданный endpoint.
Прокси особенно важен в следующих классах:
WebMapServiceImageryProviderWebMapTileServiceImageryProviderUrlTemplateImageryProviderCesiumTerrainProviderПример:
const imagery = new Cesium.WebMapServiceImageryProvider({
url: "https://external-server.com/wms",
layers: "basic",
proxy: new Cesium.DefaultProxy("/proxy/")
});
Наиболее распространённый вариант — простой HTTP-прокси на Node.js.
import express from "express";
import fetch from "node-fetch";
const app = express();
app.get("/proxy", async (req, res) => {
const targetUrl = req.query.url;
const response = await fetch(targetUrl);
const buffer = await response.arrayBuffer();
res.set("Content-Type", response.headers.get("content-type"));
res.set("Access-Control-Allow-Origin", "*");
res.send(Buffer.from(buffer));
});
app.listen(3000);
Такой слой позволяет:
Для высоконагруженных систем предпочтителен Nginx:
location /proxy/ {
proxy_pass $arg_url;
proxy_set_header Host $host;
add_header Access-Control-Allow-Origin *;
}
Использование Nginx снижает нагрузку на backend и обеспечивает более высокую производительность при массовой загрузке тайлов.
Cesium ion использует токенизированный доступ к ресурсам:
При использовании прокси важно учитывать:
Пример обработки:
fetch("/proxy?url=" + encodeURIComponent(url), {
headers: {
Authorization: `Bearer ${token}`
}
});
Прокси-сервер в CesiumJS-экосистеме часто становится точкой управления безопасностью.
Ключевые аспекты:
Без ограничений прокси может стать инструментом SSRF-уязвимости. Поэтому важно ограничивать домены:
const allowedHosts = ["server1.com", "tiles.server2.com"];
function isAllowed(url) {
const host = new URL(url).hostname;
return allowedHosts.includes(host);
}
CesiumJS чувствителен к:
Content-TypeCache-ControlAccess-Control-Allow-OriginETagНекорректная обработка может привести к:
Если CesiumJS работает по HTTPS, все проксируемые ресурсы также должны быть доступны по HTTPS.
Иначе браузер блокирует:
Прокси часто используется для принудительного перехода:
HTTP → Proxy → HTTPS
Cesium генерирует большое количество повторяющихся запросов:
Прокси должен учитывать это.
const cache = new Map();
app.get("/proxy", async (req, res) => {
const url = req.query.url;
if (cache.has(url)) {
return res.send(cache.get(url));
}
const response = await fetch(url);
const buffer = await response.buffer();
cache.set(url, buffer);
res.send(buffer);
});
Более масштабируемый вариант:
Cache-Control: public, max-age=86400
ETag: "tile-xyz"
CesiumJS автоматически использует кеш браузера, если сервер корректно выставляет заголовки.
Cesium использует внутренний планировщик запросов:
Прокси влияет на это поведение косвенно:
При неправильной конфигурации возможны:
Часто требуют проксирования из-за отсутствия CORS:
/proxy?url=https://wms.server.com?service=WMS&request=GetMap
Используются для картографических подложек:
/proxy?url=https://tiles.server.com/{z}/{x}/{y}.png
Особо чувствительны к задержкам:
Прокси должен обеспечивать минимальную задержку и поддерживать потоковую передачу.
Для векторных слоёв критична:
Некорректная передача URL приводит к:
Каждое движение камеры вызывает повторные запросы, что:
Особенно критично:
Content-TypeContent-EncodingAccess-Control-Allow-OriginТиповая промышленная архитектура:
CesiumJS
↓
Edge Proxy (Nginx / CDN)
↓
Application Proxy (Node.js)
↓
Tile Server / WMS / Cesium ion
Функции уровней:
При создании собственного провайдера:
class CustomProvider extends Cesium.ImageryProvider {
constructor(options) {
this.proxy = options.proxy;
}
requestImage(x, y, level) {
const url = this.buildUrl(x, y, level);
const proxied = this.proxy.getURL(url);
return Cesium.Resource.fetchImage({ url: proxied });
}
}
Прокси становится частью цепочки загрузки данных.
При увеличении количества пользователей прокси становится узким местом.
Основные методы оптимизации:
CesiumJS при этом продолжает работать как клиентский рендерер, не изменяя внутреннюю логику загрузки, но выигрывая от ускорения сетевого слоя.