Racelink
Документация · Данные из интернета

// Документация · Продвинутое

Данные из интернета

Прогноз погоды, таблица лиги, оповещения стрима: оверлей может обращаться к адресам, которые назвал, когда игрок согласится.

Укажите адреса в манифесте

Оверлей обращается только к Racelink, пока его манифест не назовёт адреса, а игрок их не разрешит (Безопасность):

racelink.overlay.json
"permissions": { "internet": ["api.example.com", "*.cdn.example.com"] }
  • До 20 адресов. *.example.com покрывает все поддомены.
  • Только имена хостов: без схемы, порта, пути, IP-адреса и локальных имён.
  • По HTTPS и WSS: fetch, WebSocket, а также картинки, медиа и шрифты с этих адресов.
  • Скрипты по-прежнему грузятся только из вашего пакета, какие бы адреса ни были.

Доступ разрешает игрок

Игрок видит адреса, когда добавляет оверлей, и может отказать. Может и передумать позже; тогда Racelink перезагружает оверлей, чтобы тот начал с новыми правилами. Новая версия, добавившая адрес, спрашивает снова, и новый адрес закрыт, пока игрок не согласится.

Оверлей должен работать и без интернета

overlay.permissions.internet говорит, открыты ли адреса. Проверяйте его перед запросом и показывайте что-то полезное, когда они закрыты:

src/forecast.ts
const loadForecast = async (): Promise<void> => {
if (!overlay.permissions.internet) {
forecast.textContent = 'Прогноз выключен';
return;
}
try {
const response = await fetch('https://api.example.com/forecast?track=' + trackId);
if (!response.ok) throw new Error(String(response.status));
showForecast(await response.json());
} catch {
forecast.textContent = 'Нет прогноза';
}
};
src/Forecast.tsx
export function Forecast({ overlay, trackId }: ForecastProps) {
const [data, setData] = useState<ForecastData | null>(null);
const allowed = overlay.permissions.internet;
useEffect(() => {
if (!allowed) return;
const controller = new AbortController();
fetch('https://api.example.com/forecast?track=' + trackId, { signal: controller.signal })
.then((response) => (response.ok ? response.json() : null))
.then(setData)
.catch(() => setData(null));
return () => controller.abort();
}, [allowed, trackId]);
if (!allowed) return <p className="forecast">Прогноз выключен</p>;
return data ? <ForecastView data={data} /> : <p className="forecast">Нет прогноза</p>;
}

Во время разработки страница идёт с вашего dev-сервера, и браузер применяет правила вашего сервера, а не оверлея: адрес, которого нет в манифесте, у вас работает, а у игроков — нет. Держите список в манифесте полным.