При использовании AJAX фронтенд-друзья считают, чтоNo Access-Control-Allow-Origin header
Такое сообщение об ошибке - головная боль, как запросить междоменный еще раз. Для начала статьи начнем с небольшого рассказа. . .
маленькая история
Во время разработки фронтенда детские ботиночки очень раздражались каждый раз, когда видели под браузером длинную цепочку красных сообщений об ошибках междоменных ошибок, и продолжали говорить: кто бы мне не добавил междоменный заголовок, задник -end Маленький друг будет сопротивляться, не показывая слабости: НетAccess-Control-Allow-Origin: *
Какой? Уже есть! Тогда почему он все еще выдает ошибку? Вы, должно быть, пропустили это!
Итак, битва за метание горшков вот-вот начнется...
Кому следует знать о междоменном
Честно говоря, каждый разработчик интерфейса и бэкенда должен понимать использование междоменного доступа.
Внешние партнеры могут подумать, что междоменные проблемы должны обрабатываться внутренним интерфейсом, но если вы знаете больше о заголовках ответа HTTP-запроса, вы сможете быстрее обнаруживать проблемы, быстрее разрешать исключения интерфейса и облегчать устранение неполадок. набраться терпения и прочитать эту статью.
Когда будет кросс домен
В MDN кроссдоменность объясняется следующим образом:
Совместное использование ресурсов между источниками (CORS) — это механизм, который использует дополнительные заголовки HTTP, чтобы сообщить браузерам, что веб-приложениям, работающим в одном источнике (домене), разрешен доступ к указанным ресурсам с серверов в разных источниках. Когда ресурс загружается с того же сервера, что и сам ресурсРазличные домены, протоколы или портыКогда ресурс запрашивается, ресурс инициируетHTTP-запрос между источниками.
Проще говоря, когда вы инициируете сетевой запрос к серверу в другом «домене», запрос является междоменным. Разные «домены» здесь относятся к разным протоколам, доменным именам и портам.Если какой-либо из них отличается, браузер будет рассматривать его как междоменный. Когда мы используем postman, fiddler и другие инструменты для имитации и инициирования http-запросов, мы не столкнемся с междоменными ситуациями; когда мы запрашиваем разные доменные имена в браузере, хотя запрос отправляется нормально, браузерКогда запрос возвращаетсяБудет выполнен ряд проверок, чтобы определить, является ли запрос «законным»; если это не так, возвращаемый результат будет перехвачен браузером.
Когда мы делаем POST или другие междоменные запросы, мы обнаружим, что есть только один запрос OPTIONS, и нет нужного метода запроса.
Загадочный запрос OPTIONS
Мы не отправляли запрос OPTIONS, откуда он взялся? Его имя — предварительная проверка запроса CORS, Во-первых, давайте взглянем на его официальное определение:
Метод OPTIONS HTTP используется для получения параметров связи, поддерживаемых целевым ресурсом. Клиенты могут использовать метод OPTIONS для определенного URL-адреса или для всего сайта (задав для URL значение «*»).
Опции | Это разрешено | Примечание |
---|---|---|
Request has body | No | нет тела запроса |
Successful response has body | No | Успешный ответ имеет тело ответа |
Safe | Yes | Безопасность |
Idempotent | Yes | Равенство конфиденциальности, неизменность, один и тот же интерфейс запрашивается одинаковое количество раз |
Cacheable | No | нельзя кэшировать |
Allowed in HTML forms | No | нельзя использовать в формах |
Согласно документации на официальном сайте, мы обнаружили, что он не имеет тела запроса, не может устанавливать данные и не может напрямую инициировать запрос OPTIONS. Короче говоря, запрос OPTIONS используется для запроса поддержки сервером определенных интерфейсов и других ресурсов, включая поддержку различных методов запроса и заголовков, и используется только для целей запроса.
Давайте подробно рассмотрим истинное лицо запроса OPTIONS, сначала создадим POST-запрос:
var instance = axios.create({
baseURL: 'http://192.168.0.100:8081'
})
instance({
url: '/post',
method: 'post',
data:{
url: 'xieyufei.com'
}
})
Вы можете видеть, что заголовок запроса OPTIONS очень простой, тела запроса нет, а есть два поляAccess-Control-Request-Headers
а такжеAccess-Control-Request-Method
Это новое, и использование этих двух полей будет упомянуто ниже, тогда когда будет запущен запрос OPTIONS?Здесь задействованы два запроса CORS.
две просьбы
Браузеры делят запросы CORS на две категории: простые запросы и не очень простые запросы. Простые запросы не запускают предварительные запросы CORS.
простой запрос
Если одновременно выполняются следующие два условия, это простой запрос:
-
Метод запроса является одним из следующих трех методов.
- HEAD
- GET
- POST
-
Информация заголовка HTTP не превышает следующих полей
- Accept
- Accept-Language
- Content-Language
- Content-Type ограничен тремя значениями application/x-www-form-urlencoded, multipart/form-data, text/plain
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Viewport-Width
Итак, мы просто добавляем заголовок запроса к вышеуказанному запросуContent-Type
, это не вызовет запрос OPTIONS.
instance({
url: '/post',
method: 'post',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
},
data:{
url: 'xieyufei.com'
}
})
Непростой запрос
Теперь наше внимание сосредоточено на том, когда мы делаем ajax-запросы, мы обычно добавляем пользовательские данные в заголовок запроса, поэтому большинство запросов не являются простыми запросами. Непростые запросы включают следующие поля заголовков запроса и ответа:
имя поля | Место нахождения | Применение | Примечание |
---|---|---|---|
Origin | заголовок запроса | origin | Указывает источник запроса предварительной проверки или фактический запрос. |
Access-Control-Request-Method | заголовок запроса | method | Сообщите серверу, какой метод HTTP использовать для фактического запроса. |
Access-Control-Request-Headers | заголовок запроса | field-name[, field-name]* | Сообщите серверу поля заголовка, содержащиеся в фактическом запросе. |
Access-Control-Allow-Origin | заголовок ответа | origin or * | Для запросов, которым не нужно передавать идентификационные данные, сервер может указать значение этого поля в качестве подстановочного знака, указывающего, что разрешены запросы от всех доменов. |
Access-Control-Allow-Methods | заголовок ответа | method[, method]* | Указывает методы HTTP, разрешенные для фактического запроса. |
Access-Control-Allow-Headers | заголовок ответа | field-name[, field-name]* | Указывает поля заголовка, которые разрешено использовать в фактическом запросе. |
Access-Control-Allow-Credentials | заголовок ответа | true | Указывает, разрешить ли браузеру читать содержимое ответа, если для учетных данных браузера задано значение true. |
Access-Control-Max-Age | заголовок ответа | delta-seconds | Указывает, как долго результат запроса может кэшироваться |
В приведенном выше запросе OPTIONS мы можем обнаружить, что все три заголовка запроса в таблице присутствуют в этом запросе,Access-Control-Request-Method
а такжеAccess-Control-Request-Headers
Он используется для запроса сервера.Далее я буду использовать метод POST и заголовок Content-Type для запроса.Вы можете сказать, согласны вы или нет?
На стороне сервера мы можем написать это, чтобы разрешить запросы на междоменные запросы:
const express = require('express')
const app = express()
const PORT = 8081
let allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'POST')
res.header('Access-Control-Allow-Headers', 'content-type')
next()
}
app.use(allowCrossDomain)
app.post('/post', (req, res) => {
res.json({
msg: 'hi post'
})
})
app.listen(PORT)
Вот те, с которыми хорошо знакомы наши бэкенд-друзьяAccess-Control-Allow-Origin: *
, используется для указания того, что все источники разрешают междоменное использование, что эквивалентно указанию браузеру:
Таким образом, мы можем увидеть ожидаемый нами POST-запрос, а заголовок ответа CORS включен в возвращаемую информацию заголовка; в то же время мы можем увидеть аксиомы по умолчаниюContent-Type
даapplication/json;charset=UTF-8
, не входит в число трех ограниченных значений, поэтому запускается запрос OPTIONS.
Другая информация заголовка
В дополнение к типу содержимого мы также можем добавить некоторую самоопределяемую информацию в заголовок запроса, например токен, который необходимо передать в фоновый режим.
//浏览器端
instance({
url: '/put',
method: 'put',
headers:{
'X-Custom-Header': 'xieyufei-head'
},
data:{
url: 'xieyufei.com'
}
})
//服务器端
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'POST,PUT')
res.header('Access-Control-Allow-Headers', 'content-type, X-Custom-Header')
Получить файлы cookie для разных доменов
По умолчанию файлы cookie не включаются в запросы CORS, но иногда нам необходимо использовать файлы cookie для передачи данных.Access-Control-Allow-Credentials
Поле пригодится, а вот атрибут withCredentials нужно открыть в AJAX-запросе, модифицируем код следующим образом:
//服务器端
res.header('Access-Control-Allow-Credentials', 'true')
//浏览器端
instance({
url: '/put',
method: 'put',
//新增withCredentials
withCredentials: true,
headers:{
'X-Custom-Header': 'xieyufei-head'
},
data:{
url: 'xieyufei.com'
}
})
Когда мы с нетерпением ждали открытия браузера для получения файлов cookie, мы обнаружили, что сообщается о другой ошибке:
После внимательности прочитав сообщение об ошибке, я обнаружил, что эта ошибка не совсем такая же, как и вышеупомянутый перекрестный домен, что, вероятно, означает, что при включении запрошенных идентификационных данных включены,Access-Control-Allow-Origin
Не может быть подстановочным знаком '*' (подстановочный знак). Вот мы наверное и узнали, что причина ошибки в подстановочном знаке, давайте внесем некоторые изменения в код:
const cookieParser = require('cookie-parser');
app.use(cookieParser())
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'POST')
res.header('Access-Control-Allow-Headers', 'content-type, X-Custom-Header')
res.header('Access-Control-Allow-Credentials', 'true')
app.post('/post', (req, res) => {
console.log(req.cookies, 'cookie')
res.json({
msg: 'hi post'
})
})
Теперь мы можем видеть файлы cookie, которые нам нужны.
Суммировать
Содержимое CORS на самом деле невелико и относительно просто, но это проверка практических навыков, и его обычно спрашивают во время собеседований.Поэтому вы можете создать сервер через экспресс, чтобы углубить свое понимание знаний CORS.
Для получения дополнительных статей, пожалуйста, обратите внимание на мой публичный аккаунт: Front-end One Read.