Ошибка политики CORS в действии:

Сталкивались ли вы с похожей проблемой? Или Вы видели это прямо сейчас?

При работе с API в качестве фронтенд-инженера мы часто сталкиваемся с проблемой политики CORS, и, честно говоря, в первый раз, когда я столкнулся с этой ошибкой, мне потребовалось три-четыре дня, чтобы решить ее, прежде чем я познакомился с корнем этой проблемы.

Давайте разберем его и попытаемся понять, что такое CORS и почему, черт возьми, я это понимаю?

Что такое CORS?

CORS означает совместное использование ресурсов между источниками. CORS — это механизм на основе HTTP, который позволяет серверу сообщать браузеру, что Запрос запрашивает ресурсы из другого Происхождения, то есть из другого домена.

Это может быть слишком многословно, поэтому давайте разберем это определение, чтобы понять, что такое CORS на самом деле.

Предположим, что ваш интерфейсный проект настроен на ваш локальный порт. Например: localhost: 3000

Запрос API от вашего внешнего интерфейса сначала используется вашим браузером, здесь браузер прикрепляет дополнительные заголовки, такие как: `Referer:`, `Authorization:` И другие заголовки, связанные с вашим браузером.

Совет. Вы можете проверить заголовки запроса/ответа, зайдя в инструменты разработчика Chrome, а затем на вкладку "сети".

Вот что мы теперь знаем из наших заголовков запроса:

  1. Что наш браузер из Referer: localhost:3000запрашивает ответ из другого домена с другим URL-адресом, например Request URL: https://dummy-thirdparty-API
  2. Мы не получаем никакого ответа от сервера, а также выдает ошибку политики CORS.
  3. Заметив вкладку «Заголовки», мы видим, что для политики реферера установлено значение strict-origin-when-cross-origin, что, по сути, означает, что наш браузер использует строгие политики происхождения.

Это означает, что браузер автоматически блокирует наш запрос, сделанный с нашего localhost:3000.

Почему наш браузер делает это?

По умолчанию браузеры привязаны к политике CORS. Из соображений безопасности браузеры автоматически блокируют запросы, выходящие за пределы источника (в нашем случае localhost:3000). Это означает, что веб-приложение, использующее эти API-интерфейсы, может запрашивать ресурсы только из того же источника, из которого приложение было загружено, если только ответ из других источников не включает правильные заголовки CORS.

Узнайте больше о CORS на MDN:



Теперь, когда мы поняли, что вызывает эту проблему, давайте поговорим о ее возможных решениях:

  1. Одним из возможных решений может быть добавление правильных заголовков CORS. Мы можем сделать это, установив расширение CORS для нашего браузера. Это решение имеет недостатки, когда речь идет о нашей производственной сборке, и решает проблему только для нашего собственного браузера.
  2. Второе решение — отправить запрос на прокси-сервер (подробнее об этом позже).
  3. Создание собственного прокси-сервера для повышения производительности и защиты данных. Мы также можем указать нашему серверу разрешать запросы только из нашего домена.

Что такое прокси-серверы?

Прокси-сервер — это система или приложение, которое действует как канал между клиентским приложением и сервером, когда оно запрашивает ресурсы. Проще говоря, прокси-серверы действуют как промежуточное программное обеспечение между вашим клиентом и сервером. Например. Если я запрашиваю ресурсы у стороннего API через прокси-сервер, проблема CORS никогда не возникает. Почему? Потому что политика CORS соблюдается только браузерами. Вот почему, когда мы отправляем запрос через Postman Client, мы получаем желаемый результат. Ошибка CORS возникает только при обмене данными между браузером и сервером, но не при обмене данными междусервером и сервером.

Три способа решить эту проблему:

Решение первое. Установка подключаемого модуля Allow-Access-Control-Origin (не рекомендуется)

Самый быстрый способ решить нашу проблему — установить плагин CORS, который перенаправляет и в одностороннем порядке обманывает браузер, заставляя его думать, что запрос исходит от того же сервера или что сервер разрешает запросы из любого источника. Возможно, это решит проблему, но только для вас. Вот почему это не рекомендуется, потому что, если вы создаете веб-сайт, который использует любой пользователь, после того, как пользователь отправит данные в свой браузер, появится та же ошибка политики CORS.

Это решение не решит проблему в рабочей среде, поскольку плагин CORS отключает политику браузера по умолчанию для одного и того же источника. Другими словами, для каждого запроса он добавляет заголовок Access-Control-Allow-Origin: * к ответу. Будучи дерзким, он обманывает браузер, заставляя его думать, что сервер разрешает всем источникам отправлять запрос. Этот символ * часто называют подстановочным знаком.

Access-Control-Allow-Origin: *

Решение второе: отправка запроса на прокси-сервер

Вы не можете указать пользователей в своем приложении для установки разных плагинов. Но вы можете решить эту проблему самостоятельно. Здесь мы отправляем наш запрос на прокси-сервер. Мы можем найти любой прокси-сервер, который перенаправляет наш запрос и отправляет нам ответ, тем самым избегая политики CORS в между серверами связи. Таким образом, вместо запроса целевого сервера мы отправляем запрос на прокси-сервер.

Прокси-сервер cors-anywhere как раз это и делает. Как мы теперь знаем, прокси выступает в роли посредника между клиентом и сервером. В этом случае прокси-сервер cors-anywhere работает между интерфейсным веб-приложением, отправляющим запрос, и сервером, который отвечает данными. Подобно плагину Allow-control-allow-origin, он добавляет к ответу более открытый заголовок Access-Control-Allow-Origin: *. Вы также можете искать такие серверы, которые позволяют нам отправлять запросы через них.

Но будьте осторожны и используйте только безопасные серверы, такие как серверные API от Rapid API. Вы можете проверить такие серверы здесь.

Возникает вопрос, можем ли мы реализовать собственный сервер? Конечно!

Решение третье. Создание собственного прокси-сервера (рекомендуется)

Третье исправление является наиболее удобным и безопасным из всех решений. Я рекомендую использовать этот подход, потому что, во-первых; это безопасно и, во-вторых, гибко. Кроме того, вы можете обойтись своими собственными настройками, например разрешить только свой домен в списке управления доступом. Если вы знаете Express, вы можете быстро настроить прокси-сервер или даже установить специальные пакеты для решения ваших проблем, написав всего несколько строк кода.

Вот пример экспресс-сервера:

var express = require('express'),
    request = require('request'),
    bodyParser = require('body-parser'),
    app = express();

var myLimit = typeof(process.argv[2]) != 'undefined' ? process.argv[2] : '100kb';
console.log('Using limit: ', myLimit);

app.use(bodyParser.json({limit: myLimit}));

app.all('*', function (req, res, next) {

    // Set CORS headers: allow all origins, methods, and headers: you may want to lock this down in a production environment
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Methods", "GET, PUT, PATCH, POST, DELETE");
    res.header("Access-Control-Allow-Headers", req.header('access-control-request-headers'));

    if (req.method === 'OPTIONS') {
        // CORS Preflight
        res.send();
    } else {
        var targetURL = req.header('Target-URL');
        if (!targetURL) {
            res.send(500, { error: 'There is no Target-Endpoint header in the request' });
            return;
        }
        request({ url: targetURL + req.url, method: req.method, json: req.body, headers: {'Authorization': req.header('Authorization')} },
            function (error, response, body) {
                if (error) {
                    console.error('error: ' + response.statusCode)
                }
//                console.log(body);
            }).pipe(res);
    }
});

app.set('port', process.env.PORT || 3000);

app.listen(app.get('port'), function () {
    console.log('Proxy server listening on port ' + app.get('port'));
});

Вы также можете скачать готовый прокси-сервер с github.

Просто нажмите npm install и npm serve, чтобы разместить сервер на своем localhost.

Дополнительные конфигурации, которые я хочу, чтобы вы проверили

Я наткнулся на видео Sam Meech-ward, в котором он говорит нам настроить наш сборщик, будь то Create-React-App, Vite или Parcel, в дополнение к настройке нашего прокси-сервера. Вы можете посмотреть видео здесь:

Если вы зашли так далеко, спасибо вам 👏, вы узнали что-то новое сегодня, дайте мне знать, поставив 💛 Я постараюсь опубликовать то, чему я научился в своей карьере разработки. Если у вас есть какие-либо вопросы или предложения о том, что я должен написать дальше, не стесняйтесь задавать их в разделе комментариев или обращаться ко мне в твиттере или на любой другой платформе. Я очень надеюсь, что вы решили проблему и узнали, что на самом деле скрывается за этой конкретной ошибкой. Увидимся очень, очень скоро.

-Салман