
Часть создания новых приложений связана с ошибками и поиском решений. В настоящее время я работаю над приложением, которое использует SongKick API и Spotify API для создания списков воспроизведения Spotify на основе исполнителей, выступающих в местоположении пользователя в пределах предпочтений диапазона дат. Ошибка, с которой я столкнулся, связана с Cross-Origin Resource Sharing или CORS. В этом посте обсуждается CORS, что это такое, почему это важно, как я столкнулся с CORS и как решить проблему, с которой столкнулся.
Так что же такое CORS и почему это важно?
CORS (Cross-origin resource sharing) согласно Википедии:
«Определяет способ, которым браузер и сервер могут взаимодействовать, чтобы определить, безопасно ли разрешать запрос из другого источника».
Кроме того, в современных браузерах, которые реализуют CORS всякий раз, когда информация запрашивается с одной веб-страницы на другую в разных доменах (cross-origin request), существуют определенные учетные данные и разрешения, которые должны предоставляться доменом пользователя и доменом, из которого запрашивается информация, чтобы чтобы браузер разрешил cross-origin request. Большинство современных браузеров реализуют CORS, и в настоящее время он является рекомендуемым стандартом W3C для доступа к веб-ресурсам, расположенным в разных доменах.
Почему это важно? Для вашей безопасности и безопасности окружающих. Нет, на самом деле это важная концепция безопасности, которая не позволяет CSS или Javascript запрашивать ресурсы из другого источника и предотвращает атаки скрытых хакеров. Если использовать подходящую метафору, современные веб-браузеры подобны вышибалам для частного клуба (клуб — это домен, в котором вы хотите получить информацию), если вы не знаете пароль, в который вы не входите.
Забавный факт: OWASP (Открытый проект безопасности веб-приложений) включил межсайтовый скриптинг (один из самых популярных способов обхода политик same-origin request) под номером 3 в своем списке 10 основных угроз в 2013 году, а CORS обеспечивает структуру и стандартизацию. для уменьшения этой угрозы и дает компаниям возможность обмениваться информацией, не беспокоясь о том, что они уязвимы для кибератак.
Вот еще несколько отличных ресурсов, чтобы погрузиться с головой в CORS:
- Сеть разработчиков Mozilla
- Википедия
- MaxCDN — дает отличное пошаговое описание того, как работает CORS.
Моя проблема CORS
Давайте посмотрим, как это проявляется в реальной жизни. В приложении, которое я разрабатываю, Songkick.com есть данные исполнителя, к которым мой сайт discovershowcase.herokuapp.com хочет получить доступ. Это считается cross-origin request, поскольку запрашиваемая информация поступает из другого домена. Традиционно это было бы запрещено политикой браузера того же происхождения. Однако, если CORS поддерживается, Songkick.com будет включать в свой ответ сервера то, что называется response headers, разрешая моему сайту доступ к данным. Обязательным заголовком в рамках стандарта CORS является Access-Control-Allow-Origin, за которым следуют либо определенные домены, которые могут получить доступ к данным, либо подстановочный знак *, указывающий, что любой домен может получить доступ к данным. Отсутствие этого заголовка приведет к сбою запроса CORS.
Итак, когда я развернул свое приложение на Heroku (бесплатный простой сайт, на котором размещен веб-сайт) и попытался использовать приложение в Интернете, я получил следующую ошибку:

Эта ошибка говорит о том, что API Songkick.com не отвечает с соответствующим заголовком, Access-Control-Allow-Origin, чтобы разрешить моему домену взаимодействовать с ним.
Из этой ошибки и того, что мы только что обсудили о CORS, видно, что Songkick.com не реализует CORS. После дальнейшего изучения того, что я могу сказать, Songkick не планирует в ближайшее время внедрять CORS в свой API. Поэтому мне пришлось найти способ «обойти» проблему CORS.
Как это исправить — решение
Чтобы мое приложение работало с CORS, я реализовал использование маршрута NodeJs, чтобы он действовал как прокси-сервер для получения данных из API, а не через браузер.
Когда я изначально получал ошибку, информация запрашивалась следующим образом:
My application => Browser => Songkick API => Browser => My application
И я получал сообщение об ошибке, потому что Songkick не предоставил Chrome (вышибале) соответствующий пароль. Вместо этого и после консультации с наставником вы можете запросить информацию следующим образом, чтобы обойти браузер хотя бы на начальном этапе, что позволит избежать проблем CORS header:

Давайте посмотрим на код, чтобы понять диаграмму выше.
Первый фрагмент кода (рисунок 1) — это функция, которая получает параметры из пользовательского интерфейса и затем вызывает маршрут Node "/songkick". Когда встречается строка 60 и внутри запроса axios GET вызывается переменная queryURL, это запускает маршрут Node, который приводит нас к рисунку 2 (axios — отличный http-клиент, основанный на обещаниях).

рисунок 1
На рис. 2 показан вызов абстрактного маршрута с использованием express router, который направляет маршрут "/songkick" на apiProxyController на рис. 3.

рисунок 2
Здесь, на рисунке 3, маршрут Node принимает параметры из переменной queryURL из рисунка 1 в форме req.params и вставляется в запрос данных Songkick API. (хранится как переменная url). В строке 30 выполняется GET-запрос с использованием библиотеки request, передавая url в качестве параметра. Это эффективно обходит браузер, избегая проблемы CORS, поскольку теперь запрос поступает с маршрута сервера, а не из браузера.
Поскольку этот маршрут сначала вызывается в функции getConcerts из рис. 1, после завершения запроса GET результаты возвращаются и обрабатываются внутри блока .then((results)=>{}) в строке 61, рис. 1. >.

рисунок 3
Итак, решение?
- Создайте маршрут сервера, который будет запускаться пользователем через пользовательский интерфейс.
- Убедитесь, что он фиксирует все соответствующие параметры
- Используйте библиотеку HTTP-запросов, например axios или request, чтобы сделать запрос к рассматриваемому API (эффективно обходя проблему CORS)
- Верните результаты в браузер и обработайте данные.
Примечание. Вам не нужно заключать вызов request в вызов axios, маршрут сервера сам по себе должен помочь. Но в моем случае у меня уже было довольно много кода для обработки результатов внутри вызова axios, поэтому на данный момент и до тех пор, пока я не рефакторинг, это работает для меня.
До скорого…
Кричать
- Музыка, которую слушали во время ведения блога: Youngr — «Out Of My System»
- Спасибо Брайану Доялу, моему инструктору Bootcamp и наставнику за помощь в диагностике и поиске решения
Первоначально опубликовано на thefinleycode.com