Приложение JavaScript, запущенное в браузере, обычно может получать доступ к ресурсам HTTP только из того же домена (источника), который их обслуживает.
Загрузка изображений или сценариев/стилей из одного источника всегда работает. Кроме того, при загрузке веб-шрифтов с помощью @font-face
по умолчанию установлена политика “того же происхождения”. Аналогично с другими, менее популярными вещами (такими как текстуры WebGL и drawImage
ресурсы, загруженные в API Canvas).
Однако вызовы XHR и Fetch на внешний сторонний сервер завершатся ошибкой. Это если только сторонний сервер не реализует механизм, позволяющий устанавливать соединение и запрашивать ресурсы для загрузки и использования.
Этот механизм называется CORS , Совместное использование ресурсов из разных источников .
Одна очень важная вещь, которая нуждается в CORS, – это модули ES, недавно представленные в современных браузерах.
Если вы не настроите политику CORS на сервере , которая позволяет ему обслуживать сторонние источники, запрос не будет выполнен.
Пример выборки:
Пример XHR:
Ресурс из разных источников не работает, если он:
- в другой домен
- в другой поддомен
- на другой порт
- к другому протоколу
ЯДРА предназначены для вашей безопасности, чтобы предотвратить использование злоумышленниками любой веб-платформы, которую вы используете.
Если вы управляете обоими серверами и клиент, вы знаете, что обе стороны заслуживают доверия, и поэтому у вас есть веские основания разрешить совместное использование ресурсов.
Как?
Это зависит от вашего стека на стороне сервера.
Поддержка браузера
Довольно хорошо (в основном все, кроме IE<10):
Пример с Экспресс
Если вы используете Node.js и выразите в качестве основы, используйте пакет промежуточного программного обеспечения CORS .
Вот простая реализация экспресс- Node.js сервер:
const express = require('express') const app = express() app.get('/without-cors', (req, res, next) => { res.json({ msg: '😞 no CORS, no party!' }) }) const server = app.listen(3000, () => { console.log('Listening on port %s', server.address().port) })
Если вы нажмете /без ядер
с запросом на выборку из другого источника, это вызовет проблему CORS.
Все, что вам нужно сделать, чтобы все работало гладко, – это запросить пакет cors
, связанный выше, и передать его в качестве функции промежуточного программного обеспечения обработчику запросов конечной точки:
const express = require('express') const cors = require('cors') const app = express() app.get('/with-cors', cors(), (req, res, next) => { res.json({ msg: 'WHOAH with CORS it works! 🔝 🎉' }) }) /* the rest of the app */
Я сделал простой пример сбоя, вот его код: https://glitch.com/edit/#!/флавио-корс-клиент .
Это и есть Node.js Экспресс-сервер: https://glitch.com/edit/#!/флавиокопы-cors-пример-экспресс
Обратите внимание, что запрос, который завершается ошибкой из-за того, что сервер неправильно обрабатывает заголовки CORS, все еще принимается. Как вы можете видеть на панели “Сеть”, где вы можете увидеть сообщение, отправленное сервером:
Разрешать только определенные источники
Однако в этом примере есть проблема: ЛЮБОЙ запрос будет принят сервером как исходящий из другого источника.
Как вы можете видеть на панели “Сеть”, переданный запрос имеет заголовок ответа access-control-allow-origin: *
:
Вам необходимо настроить сервер так, чтобы разрешать обслуживание только одного источника и блокировать все остальные.
Используя тот же cors
Библиотека узлов, вот как бы вы это сделали:
const cors = require('cors') const corsOptions = { origin: 'https://yourdomain.com', } app.get('/products/:id', cors(corsOptions), (req, res, next) => { //... })
Вы также можете подавать больше:
const whitelist = ['http://example1.com', 'http://example2.com'] const corsOptions = { origin: function (origin, callback) { if (whitelist.indexOf(origin) !== -1) { callback(null, true) } else { callback(new Error('Not allowed by CORS')) } }, }
Предполетная подготовка
Есть некоторые запросы, которые обрабатываются “простым” способом. Все Запросы GET
принадлежат к этой группе.
Также некоторые пост
и ГОЛОВА
запросы делают то же самое.
Запросы POST
также входят в эту группу, если они удовлетворяют требованию использования типа контента
приложение/x-www-форма-urlencoded
составная часть/форма-данные
текст/обычный
Все остальные запросы должны проходить этап предварительного утверждения, называемый предполетным. Браузер делает это, чтобы определить, есть ли у него разрешение на выполнение действия, отправив запрос ПАРАМЕТРЫ
.
Предполетный запрос содержит несколько заголовков, которые сервер будет использовать для проверки разрешений (не относящиеся к делу поля опущены):
OPTIONS /the/resource/you/request Access-Control-Request-Method: POST Access-Control-Request-Headers: origin, x-requested-with, accept Origin: https://your-origin.com
Сервер ответит примерно так (не относящиеся к делу поля опущены):
HTTP/1.1 200 OK Access-Control-Allow-Origin: https://your-origin.com Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Мы проверили наличие POST, но сервер сообщает нам, что мы также можем выдавать другие типы HTTP-запросов для этого конкретного ресурса.
Следуя Node.js В приведенном выше примере сервер также должен обработать запрос ПАРАМЕТРОВ:
var express = require('express') var cors = require('cors') var app = express() //allow OPTIONS on just one resource app.options('/the/resource/you/request', cors()) //allow OPTIONS on all resources app.options('*', cors())
Оригинал: “https://flaviocopes.com/express-cors/”