CORS настройки

CORS (Cross-Origin Resource Sharing) — это механизм, позволяющий браузеру контролировать доступ веб-приложений к ресурсам, расположенным на других доменах. В контексте Stencil важно понимать, что сам фреймворк не управляет CORS напрямую: все запросы к сторонним API выполняются через стандартные браузерные механизмы (fetch, XMLHttpRequest). Настройка CORS требует правильной конфигурации сервера, к которому осуществляется запрос.

Проблемы, возникающие при кросс-доменных запросах

При попытке обратиться к ресурсам с другого домена без корректных заголовков сервер возвращает ошибку вида:

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

Основные причины:

  • Отсутствие заголовка Access-Control-Allow-Origin на сервере.
  • Запрос включает нестандартные заголовки (Authorization, Content-Type: application/json) или методы (PUT, DELETE), что требует preflight-запроса (OPTIONS).
  • Сервер не разрешает использование cookies или credential-запросов при кросс-доменном доступе.

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

Для корректной работы Stencil-компонентов с внешними API необходимо:

  1. Разрешить домен фронтенда:
Access-Control-Allow-Origin: http://localhost:3333

Или использовать универсальный доступ (не рекомендуется для production):

Access-Control-Allow-Origin: *
  1. Разрешить методы, используемые приложением:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
  1. Разрешить заголовки, отправляемые клиентом:
Access-Control-Allow-Headers: Content-Type, Authorization
  1. Разрешить использование credential-запросов:
Access-Control-Allow-Credentials: true

Настройка CORS при разработке Stencil-приложения

Stencil использует Dev Server, который может проксировать запросы к API, обходя ограничения CORS. В файле stencil.config.ts можно настроить прокси:

import { Config } from '@stencil/core';

export const config: Config = {
  devServer: {
    proxy: {
      '/api': {
        target: 'https://example.com',
        changeOrigin: true,
        secure: false,
      },
    },
  },
};

Пояснения:

  • /api — путь, на который будут перенаправляться запросы.
  • target — адрес внешнего API.
  • changeOrigin: true — заменяет заголовок Origin на адрес целевого сервера.
  • secure: false — отключает проверку SSL-сертификата для локальной разработки.

Таким образом, все запросы к /api/... внутри Stencil-приложения будут автоматически проксироваться, и браузер не заблокирует их из-за CORS.

Работа с fetch и credentials

При запросах, где требуется авторизация через cookie или токен, необходимо учитывать параметры fetch:

fetch('https://example.com/api/data', {
  method: 'GET',
  credentials: 'include', // отправка cookie
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer TOKEN'
  }
})

Ключевые моменты:

  • credentials: 'include' позволяет отправлять cookie вместе с запросом.
  • Для работы с credential-запросами сервер обязан выставить Access-Control-Allow-Credentials: true и не использовать * в Access-Control-Allow-Origin.

Preflight-запросы

Когда отправляется запрос с методами, отличными от GET/POST, или с нестандартными заголовками, браузер выполняет preflight-запрос типа OPTIONS. Сервер должен корректно его обрабатывать:

OPTIONS /api/data HTTP/1.1
Origin: http://localhost:3333
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

Ответ сервера:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http://localhost:3333
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type

Если сервер игнорирует preflight-запрос, основной запрос будет заблокирован браузером.

Рекомендации по организации API для Stencil

  • Настраивать CORS на уровне сервера для каждого домена фронтенда.
  • Использовать прокси Dev Server для локальной разработки.
  • Всегда проверять наличие preflight-запросов при использовании нестандартных заголовков или методов.
  • Для credential-запросов никогда не использовать * в Access-Control-Allow-Origin.

Практический пример

Предположим, Stencil-компонент должен получать список пользователей с внешнего API:

@Component({
  tag: 'user-list',
  styleUrl: 'user-list.css',
  shadow: true
})
export class UserList {
  @State() users: any[] = [];

  async componentWillLoad() {
    try {
      const res = await fetch('/api/users', { credentials: 'include' });
      this.users = await res.json();
    } catch (e) {
      console.error('Ошибка запроса:', e);
    }
  }

  render() {
    return (
      <ul>
        {this.users.map(user => (
          <li>{user.name}</li>
        ))}
      </ul>
    );
  }
}

Здесь '/api/users' проксируется через Dev Server к реальному серверу, а все настройки CORS обрабатываются на сервере.


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