Введение в совместное использование ресурсов между источниками, способ позволить клиентам и серверам обмениваться данными, даже если они не находятся в одном домене.
Приложение JavaScript, запущенное в браузере, обычно может получить доступ к ресурсам HTTP только в том же домене (источнике), который его обслуживает.
Загрузка изображений или скриптов / стилей всегда работает, ноXHRиПринестивызовы на другой сервер не будут выполнены, если этот сервер не реализует способ разрешить это соединение.
Этот способ называется CORS,Совместное использование ресурсов между источниками.
Также загрузка веб-шрифтов с помощью@font-face
имеет политику одинакового происхождения по умолчанию и другие менее популярные вещи (например, текстуры WebGL иdrawImage
ресурсы, загруженные в Canvas API).
Одна очень важная вещь, которая требует CORS, - этоМодули ES, недавно представленный в современных браузерах.
Если вы не настроили политику CORSна серверечто позволяет обслуживать сторонние источники, запрос не будет выполнен.
Пример получения:
Пример XHR:
Ресурс Cross-Origin не работает, если он:
- к другомудомен
- к другомусубдомен
- к другомупорт
- к другомупротокол
и это там для вашей безопасности, чтобы предотвратить использование злоумышленникамиВеб-платформа.
Но если вы контролируете и сервер, и клиент, у вас есть все веские причины позволить им общаться друг с другом.
Как?
Это зависит от вашего серверного стека.
Поддержка браузера
Довольно неплохо (в основном все, кроме IE <10):
Пример с Экспресс
Если вы используете Node.js и Express в качестве фреймворка, используйтеПакет промежуточного программного обеспечения CORS.
Вот простая реализация ExpressNode.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)
})
Если ты ударил/without-cors
с запросом на выборку из другого источника, это поднимет проблему 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 */
Я сделал простой пример Glitch, вот его код:https://glitch.com/edit/#!/flavio-cors-client.
Это сервер Node.js Express:https://glitch.com/edit/#!/flaviocopes-cors-example-express
Обратите внимание на то, что запрос, который не выполняется, потому что он не обрабатывает заголовки CORS правильно, все еще принимается, как вы можете видеть на панели Network, где вы найдете сообщение, отправленное сервером:
Разрешить только определенное происхождение
Однако в этом примере есть проблема: ЛЮБОЙ запрос будет принят сервером как кросс-источник.
Как вы можете видеть на панели «Сеть», у прошедшего запроса есть заголовок ответа.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
иHEAD
запросы тоже.
POST
запросы также входят в эту группу, если они удовлетворяют требованию использования Content-Type
application/x-www-form-urlencoded
multipart/form-data
text/plain
Все остальные запросы должны проходить этап предварительного утверждения, называемый предполетной проверкой. Браузер делает это, чтобы определить, есть ли у него разрешение на выполнение действия, выдаваяOPTIONS
запрос.
Предварительный запрос содержит несколько заголовков, которые сервер будет использовать для проверки разрешений (нерелевантные поля опущены):
OPTIONS /the/resource/you/request
Access-Control-Request-Method: POST
Access-Control-Request-Headers: origin, x-requested-with, accept
Origin: https://your-origin.comThe server will respond with something like this(irrelevant fields omitted):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://your-origin.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETEWe checked for POST, but the server tells us we can also issue other HTTP request types for that particular resource.
Following the Node.js Express example above, the server must also handle the OPTIONS request:
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())
Download my free JavaScript Beginner's Handbook
More browser tutorials:
- Some useful tricks available in HTML5
- How I made a CMS-based website work offline
- The Complete Guide to Progressive Web Apps
- The Fetch API
- The Push API Guide
- The Channel Messaging API
- Service Workers Tutorial
- The Cache API Guide
- The Notification API Guide
- Dive into IndexedDB
- The Selectors API: querySelector and querySelectorAll
- Efficiently load JavaScript with defer and async
- The Document Object Model (DOM)
- The Web Storage API: local storage and session storage
- Learn how HTTP Cookies work
- The History API
- The WebP Image Format
- XMLHttpRequest (XHR)
- An in-depth SVG tutorial
- What are Data URLs
- Roadmap to learn the Web Platform
- CORS, Cross-Origin Resource Sharing
- Web Workers
- The requestAnimationFrame() guide
- What is the Doctype
- Working with the DevTools Console and the Console API
- The Speech Synthesis API
- How to wait for the DOM ready event in plain JavaScript
- How to add a class to a DOM element
- How to loop over DOM elements from querySelectorAll
- How to remove a class from a DOM element
- How to check if a DOM element has a class
- How to change a DOM node value
- How to add a click event to a list of DOM elements returned from querySelectorAll
- WebRTC, the Real Time Web API
- How to get the scroll position of an element in JavaScript
- How to replace a DOM element
- How to only accept images in an input file field
- Why use a preview version of a browser?
- The Blob Object
- The File Object
- The FileReader Object
- The FileList Object
- ArrayBuffer
- ArrayBufferView
- The URL Object
- Typed Arrays
- The DataView Object
- The BroadcastChannel API
- The Streams API
- The FormData Object
- The Navigator Object
- How to use the Geolocation API
- How to use getUserMedia()
- How to use the Drag and Drop API
- How to work with scrolling on Web Pages
- Handling forms in JavaScript
- Keyboard events
- Mouse events
- Touch events
- How to remove all children from a DOM element
- How to create an HTML attribute using vanilla Javascript
- How to check if a checkbox is checked using JavaScript?
- How to copy to the clipboard using JavaScript
- How to disable a button using JavaScript
- How to make a page editable in the browser
- How to get query string values in JavaScript with URLSearchParams
- How to remove all CSS from a page at once
- How to use insertAdjacentHTML
- Safari, warn before quitting
- How to add an image to the DOM using JavaScript
- How to reset a form
- How to use Google Fonts