GuardLabs
demo / squarespace-proxy
Squarespace · code injection

Внешние API на Squarespace: почему fetch падает и как это чинится прокси

На Squarespace нет серверного кода: только статика и клиентский JS через Code Injection. Как только виджету нужны данные внешнего API, всплывают две стены: CORS и невозможность спрятать API-ключ. Ниже обе стены показаны вживую, вместе с рабочим обходом.

Боль

Две стены, о которые бьются виджеты на Squarespace

Стена 1: CORS

  • Браузер блокирует fetch к API, которое не отдаёт заголовок Access-Control-Allow-Origin.
  • Классический симптом: в консоли «blocked by CORS policy», а из curl тот же адрес работает.
  • Со стороны Squarespace это не чинится вообще: серверной части, куда можно перенести запрос, у платформы нет.

Стена 2: API-ключи

  • Ключ, вставленный в Code Injection, виден каждому посетителю через view-source.
  • Для платных API это прямой путь к чужим счетам за ваш ключ.
  • Вывод тот же: секреты должны жить на стороне, которой у Squarespace нет.

Живой артефакт

Курсы валют ПриватБанка: напрямую и через прокси

API ПриватБанка не отдаёт CORS-заголовки, поэтому запрос из браузера падает. Наш тонкий прокси на этом же домене снимает проблему. Обе кнопки делают настоящие сетевые запросы, лог справа пишется в реальном времени.

Курс валют

Нажмите одну из кнопок выше.
// лог запросов появится здесь

Решение

Тонкий прокси: десять строк конфигурации вместо бэкенда

Что делает прокси

  • Принимает запрос с сайта, сам ходит во внешний API с сервера и возвращает ответ с правильным CORS-заголовком.
  • API-ключ хранится в конфигурации прокси и в браузер не попадает никогда.
  • На стенде прокси поднят на nginx. Клиенту без своего сервера то же самое делается бесплатным Cloudflare Worker.

Вариант для клиента: Cloudflare Worker

export default {
  async fetch(request, env) {
    const upstream = await fetch(
      "https://api.example.com/data",
      { headers: { "X-Api-Key": env.SECRET_KEY } }
    );
    const body = await upstream.text();
    return new Response(body, {
      headers: {
        "Content-Type": "application/json",
        "Access-Control-Allow-Origin": "https://вашсайт.com",
      },
    });
  },
};

Вставка виджета в Squarespace

  1. Страница в Squarespace: настройки страницы, вкладка Advanced, Page Header Code Injection. Тариф Core или выше, на Basic вставки кода нет.
  2. Виджет обращается только к адресу прокси, ни одного прямого вызова внешнего API из браузера.
  3. В прокси прописывается точный Origin сайта клиента, а не звёздочка, чтобы данными не пользовались чужие страницы.

Как проверить

Проверка за две минуты

  1. Нажмите «Запрос напрямую»: в логе появится ошибка сети. Откройте консоль DevTools и увидите формулировку браузера про CORS policy.
  2. Нажмите «Запрос через прокси»: те же данные ПриватБанка приходят и рендерятся в таблицу.
  3. Вкладка Network в DevTools: успешный запрос идёт на guardlabs.online, а не на api.privatbank.ua, значит секреты и лимиты остаются на сервере.
  4. Проверьте адрес прокси curl-ом со своего компьютера: curl https://guardlabs.online/demo/squarespace-proxy/api/rates