Обзор

Последнее обновление: февраль 2022 г.

Оригинал статьи о Сообществе разработчиков Refinitiv доступен здесь.

Веб-API RESTful (или просто REST API) сегодня являются основным стандартом индустрии программного обеспечения. API-интерфейсы свободно основаны на методах HTTP, к которым легко получить доступ с любого языка программирования, платформы, устройства и ОС. Облачные технологии и интернет-сервисы используют API-интерфейсы REST, чтобы приложение или служба могли подключаться к ним.

Однако, если вы являетесь веб-разработчиком, ваше клиентское приложение JavaScript не может напрямую подключаться к этим веб-службам RESTful из-за политики Same-origin. Все веб-браузеры применяют эту политику, чтобы предотвратить доступ браузеров к различным ресурсам домена/сервера. И, конечно же, ваш веб-сервер/домен веб-приложения всегда отличается от облачных сервисов, потому что они размещены на разных сайтах.

В этом примере проекта показано, как использовать обратный прокси-сервер, чтобы JavaScript в веб-браузере мог подключаться и использовать данные из службы RESTful, используя API Refinitiv Data Platform (RDP) в качестве примера REST API. Он использует модуль http-proxy и веб-фреймворк Express.js для функций веб-сервера и обратного прокси.

Примечание. Обратите внимание, что эта статья и примеры проектов предназначены только для целей разработки и POC. Этот вид реализации обратного прокси-сервера не рекомендуется для использования в производственной среде. Вы можете использовать сервер де-факто, такой как Nginx, для обратного прокси-сервера в вашей среде. В качестве альтернативы вы можете использовать Неявный грант RDP.en/api-catalog/refinitiv-data-platform/refinitiv-data-platform-apis/tutorials#authorization-for-browser-based-applications).

Зачем нам нужен обратный прокси?

Вернемся к первому вопросу: почему веб-браузеры не могут напрямую подключаться к RDP API? Как правило, веб-браузеры не разрешают вашему коду JavaScript вызывать сторонний веб-API, который находится на другом сервере (междоменный запрос). Браузеры разрешают только HTTP-ответ с заголовком Control-Allow-Origin (Cross-Origin Resource Sharing — CORS) со значением * или доменом вашего клиента. В качестве примера см. следующий сценарий.

В приведенном выше сценарии браузер открывает файл из локального местоположения файла file:///C:/drive_d/Project/Code/RDP_HTTP_PROXY/public/index.html.

  1. Это означает, что домен этой сети находится на локальной машине (file:///C).
  2. Приложение JavaScript отправляет сообщение запроса аутентификации в службу аутентификации RDP по URL-адресу https://api.refinitiv.com, который находится в другом домене.
  3. Браузер блокирует запрос и выдает сообщение об ошибке CORS (Cross-Origin Resource Sharing).
  4. JavaScript получает сообщение об ошибке, а не токены RDP, поэтому он не может продолжать запрашивать данные с другими конечными точками RDP.

Поведение этого браузера можно проиллюстрировать следующей диаграммой.

Сторонние веб-API не обязательно должны быть конкретно RDP, это может быть ваша микрослужба, которая также размещена в другом домене. Итак, как мы можем справиться с этим? Вы можете создать шлюз API в качестве обратного прокси-сервера для перенаправления трафика на различные службы в соответствии с URL-адресом запроса.

По состоянию на февраль 2022 г. Некоторые сервисы RDP, такие как экологические, социальные и управленческие (ESG), новости, символы и т. д., поддерживают междоменное управление-разрешение-происхождение. Вы можете вызывать их непосредственно из веб-браузеров (если у вас уже есть токен доступа). Однако я собираюсь применить эти вызовы к прокси-серверу для упрощения управления и предотвращения любых будущих изменений.

Вы можете использовать другие библиотеки/инструменты для работы с прокси, например, проект Refinitiv-API-Samples/Example.RDPAPI.TypeScript.AngularESGWebapp, который использует платформу Angular в качестве прокси на стороне клиента.

Примечание. Позвольте мне еще раз напомнить вам, что эта реализация прокси-сервера предназначена только для целей разработки и POC. Не рекомендуется для использования в производстве. Вы можете использовать сервер де-факто, такой как Nginx, для обратного прокси-сервера в вашей среде. В качестве альтернативы вы можете использовать Неявный грант RDP.

Что такое API Refinitiv Data Platform (RDP)?

API Refinitiv Data Platform (RDP) предоставляют разработчикам различные данные и контент Refinitiv через простой в использовании веб-API.

API-интерфейсы RDP предоставляют разработчикам беспрепятственный и целостный доступ ко всему контенту Refinitiv, такому как история ценообразования, экологические, социальные и управленческие (ESG), новости, исследования и т. д., а также к их контенту, обогащая, интегрируя и распространяя данные через единый интерфейс. , доставлены туда, куда им это нужно. Механизмы доставки RDP API следующие:

  • Запрос — ответ: веб-служба RESTful (HTTP GET, POST, PUT или DELETE)
  • Оповещение: доставка — это механизм получения асинхронных обновлений (предупреждений) для подписки.
  • Пакеты: доставляйте существенные полезные данные, такие как данные о ценах на конец дня для всего места проведения.
  • Потоковая передача: доставка сообщений в режиме реального времени.

Этот пример проекта фокусируется только на методе доставки веб-сервиса Request-Response: RESTful.

Express.js с HTTP-прокси

Начнем с серверного приложения. В этом примере используется Node.js с фреймворками Express.js.

Настроить веб-сервер Express.js

Во-первых, создайте веб-сервер с Express.js для обслуживания статического содержимого (доступно в папке с именем public). Файл сервера называется server.js.

Настройте HTTP-прокси для обратного прокси-сервера аутентификации RDP

Затем создайте прокси-объект как объект apiProxy с модулем http-proxy в файле server.js.

Затем примените URL RDP API https://api.refinitiv.com к маршруту apiProxy и Express.js /auth/oauth2/<version>/*.

Приведенный выше код обрабатывает HTTP Post для маршрута операции /auth/oauth2/<version>/*, а затем использует функцию http-proxy web() для перенаправления входящего сообщения HTTP-запроса (тело запроса, заголовки запроса, аутентификация запроса и т. д.) на целевой сервер RDP API следующим образом:

  • Перенаправить входящее сообщение запроса HTTP Post для /auth/oauth2/v1/token на конечную точку RDP https://api.refinitiv.com/auth/oauth2/v1/token.
  • Перенаправить входящее сообщение запроса HTTP Post для /auth/oauth2/v1/revoke на конечную точку RDP https://api.refinitiv.com/auth/oauth2/v1/revoke.

Обратите внимание, что я храню все версии конечных точек RDP в переменной Environment, поэтому, если есть какое-либо обновление версии, мне не нужно менять исходный код.

Пример переменных среды (или файла .env):

RDP_BASE_URL=https://api.refinitiv.com
RDP_AUTH_VERSION=v1
RDP_ESG_VERSION=v2
RDP_SYMBOLOGY_VERSION=v1
RDP_NEWS_VERSION=v1

Настройте обратный прокси-сервер для других конечных точек

Затем добавьте дополнительные обработчики маршрутов HTTP для служб ESG, News и Symbology.

Приведенный выше код обрабатывает операции HTTP для сообщений запроса RDP, а затем перенаправляет входящее сообщение запроса HTTP (тело запроса, заголовки запроса, запрос аутентификации и т. д.) на целевой сервер RDP API с функцией http-proxy web() следующим образом:

  • Перенаправить входящее сообщение запроса HTTP Post для /discovery/symbology/v1/lookup на конечную точку RDP https://api.refinitiv.com/discovery/symbology/v1/lookup.
  • Перенаправить входящее сообщение запроса HTTP Get для /data/environmental-social-governance/v2/views/* на конечную точку RDP https://api.refinitiv.com/data/environmental-social-governance/v2/views/*.
  • Перенаправить входящее сообщение запроса HTTP Get для /data/news/v1/headlines/ на конечную точку RDP https://api.refinitiv.com/data/news/v1/headlines/.

Теперь приложение веб-сервера server.js готово обслуживать статическое содержимое и выполняет обратный прокси операций RDP.

Клиентский JavaScript

Переходим к клиентскому JavaScript в веб-браузерах. В этом примере используется ванильный JavaScript (также известный как чистый JavaScript), поэтому ту же концепцию можно применить и к любой среде JavaScript. Файл приложения JavaScript на стороне клиента называется app.js.

Авторизация токенов RDP

Проверка прав RDP API основана на спецификации OAuth 2.0. Первым шагом рабочего процесса приложения является получение токена, который позволит получить доступ к защищенному ресурсу, то есть API REST данных. Для API требуются следующие учетные данные для доступа:

  • Имя пользователя: имя пользователя.
  • Пароль: пароль, связанный с именем пользователя.
  • Идентификатор клиента: также известен как AppKey и генерируется с помощью генератора ключей приложения. Этот уникальный идентификатор определяется для пользователя или приложения и считается конфиденциальным (не передается пользователям). Параметр client_id может быть передан в теле запроса или как заголовок запроса «Авторизация», который закодирован как base64.

Приложение должно отправить сообщение HTTP Post с учетными данными для доступа к конечной точке службы аутентификации RDP. Однако служба проверки подлинности RDP не поддерживает CORS, поэтому клиентское приложение вместо этого отправляет сообщение запроса проверки подлинности на прокси-сервер (server.js) /auth/oauth2/v1/token конечной точки. server.js просто перенаправляет наше сообщение HTTP Post на сервер RDP и перенаправляет ответное сообщение RDP обратно на app.js.

Функция authenRDP() использует Fetch API для отправки сообщений HTTP-запросов как для первого входа в систему (authReq['grant_type'] = 'password'), так и для сценария обновления токена (authReq['grant_type'] = 'refresh_token') в службу аутентификации RDP (через server.js).

После успешной аутентификации функция получает ответное сообщение службы аутентификации RDP (через server.js) и сохраняет следующую информацию о токене RDP в переменных на стороне клиента.

  • access_token: токен, используемый для вызова вызовов API данных REST, как описано выше. Приложение должно сохранить эти учетные данные для дальнейших запросов RDP/Refinitiv Real-Time — Optimized.
  • refresh_token: токен обновления, который будет использоваться для получения обновленного токена доступа до истечения срока действия. Приложение должно сохранить эти учетные данные для обновления токена доступа.
  • expires_in: время действия токена доступа в секундах.

Полную информацию и объяснение рабочего процесса приложения процесса аутентификации RDP см. в следующих руководствах по RDP APIS:

Обновление токенов RDP

Перед истечением срока действия сеанса приложению необходимо отправить сообщение запроса Refresh Grant, чтобы получить новый маркер доступа. Давайте изменим функцию authenRDP(), чтобы она также поддерживала запрос Refresh Grant.

Теперь app.js поддерживает сценарии предоставления пароля и предоставления обновления для RDP API с помощью одной функции authenRDP(). Это относится к части аутентификации клиентского приложения app.js.

Запрос данных RDP API

Это подводит нас к запросу данных RDP API. Все последующие вызовы REST API используют токен доступа через заголовок сообщения HTTP-запроса Авторизация, как показано ниже, для получения данных.

  • Заголовок:
  • Авторизация = Bearer <RDP Access Token>

Обратите внимание на пробел между значениями Bearer и RDP Access Token.

Затем приложение создает сообщение запроса в формате сообщения JSON или параметр запроса URL на основе интересующей службы и отправляет его как сообщение запроса HTTP в конечную точку службы. Разработчики могут получить API-интерфейсы RDP, конечную точку службы, операции HTTP и параметры на странице API Playground Refinitiv Data Platform, к которой разработчики интерактивного сайта документации могут получить доступ, если у них есть действующая учетная запись Refinitiv Data Platform.

Этот проект демонстрирует следующие службы RDP:

  • ESG Service /views/basic операция, предоставляющая базовый обзор 6 общих данных ESG для потребителей.
  • Служба новостей /headlines операция.
  • Конечная точка службы обнаружения /lookup, которая перемещается между идентификаторами или сопоставляет идентификаторы с идентификаторами PermID.

Все сообщения HTTP-запросов от app.js на стороне клиента отправляются на server.js. Модуль http-proxy перенаправляет сообщение запроса в службу RDP и пересылает ответное сообщение от RDP на сторону клиента.

Примечание. По состоянию на февраль 2022 года текущая версия службы RDP ESG — v2.

Функция getSymbology() поддерживает два сценария: преобразование кода RIC в коды ISIN и биржевых тикеров и преобразование кода RIC в код PermID. Разница заключается в теле запроса JSON. Пользователи могут нажимать кнопки, чтобы выбрать сценарий для выполнения.

В приведенном ниже коде показано, как преобразовать код RIC в коды ISIN и биржевых тикеров.

Функция getSymbology() поддерживает два сценария: преобразование кода RIC в коды ISIN и биржевых тикеров и преобразование кода RIC в код PermID. Разница заключается в теле запроса JSON. Пользователи могут нажимать кнопки, чтобы выбрать сценарий для выполнения.

В приведенном ниже коде показано, как преобразовать код RIC в коды ISIN и биржевых тикеров.

В приведенном ниже коде показано, как преобразовать код RIC в код PermID.

Это охватывает базовый рабочий процесс HTTP-операций кода app.js на стороне клиента. Пример веб-приложения теперь может войти в RDP, получить токен доступа и запросить данные через http-прокси.

Предпосылка

Для этого демонстрационного проекта требуется следующее программное обеспечение зависимостей.

  1. Учетные данные RDP-доступа.
  2. Среда выполнения JavaScript Node.js.
  3. Интернет-соединение.
  4. Docker Desktop/Engine, если вы хотите работать с Docker.

Пожалуйста, свяжитесь с вашим представителем Refinitiv, чтобы помочь вам получить доступ к учетной записи и услугам RDP. Дополнительные сведения об учетных данных для доступа по протоколу RDP, настроенных при аренде, см. в разделе Начало работы для идентификатора пользователя статьи Начало работы с Refinitiv Data Platform.

Как запустить пример с Docker

Во-первых, перейдите в папку проекта и создайте имя файла .env со следующим содержимым.

RDP_BASE_URL=https://api.refinitiv.com
RDP_AUTH_VERSION=v1
RDP_ESG_VERSION=v2
RDP_SYMBOLOGY_VERSION=v1
RDP_NEWS_VERSION=v1

Затем запустите команду $> docker build -t <project tag name> . в консоли, чтобы создать образ из Dockerfile.

$> docker build -t rdp-http-proxy .

После успешной сборки вы можете создать и запустить контейнер с помощью следующей команды

$> docker run --name rdp-http-proxy -it --env-file .env -p 8080:8080 rdp-http-proxy

Откройте URL-адрес http://localhost:8080 в веб-браузере, чтобы запустить пример веб-приложения.

Вы можете нажать кнопки Ctrl+C, чтобы выйти из серверного приложения, затем остановить и удалить контейнер с помощью следующих команд.

$> docker stop rdp-http-proxy
$> docker rm rdp-http-proxy

Кроме того, вы можете настроить и запустить проект вручную, следуя инструкциям в GitHub.

Поиск неисправностей

Вопрос. Я дважды щелкаю файл index.html, чтобы открыть пример веб-приложения, ввожу свои учетные данные RDP и нажимаю кнопку аутентификации. На странице отображается сообщение об ошибке TypeError: Failed to fetch.

Ответ. Вы не можете запустить пример, просто дважды щелкнув файл index.html. Вам нужно запустить пример веб-сервера и открыть пример веб-приложения с URL-адресом http:localhost:8080 в веб-браузере.

Вопрос: я пытаюсь запустить веб-сервер с помощью команды npm start, но он показывает сообщение об ошибке Ошибка: не удается найти модуль 'express'.

Ответ: вам необходимо установить зависимости проекта с помощью команды npm install перед запуском команды npm start.

Вопрос: у меня нет учетных данных RDP.

Ответ: обратитесь к представителю Refinitiv, чтобы получить доступ к учетной записи RDP и службам.

Вопрос. Я получил сообщение об ошибке {"error":"access_denied"}, когда нажимаю кнопку аутентификации.

Ответ. Это сообщение об ошибке означает, что ваши учетные данные RDP не имеют разрешения на доступ к API. Пожалуйста, свяжитесь с представителем Refinitiv, чтобы подтвердить разрешение вашей учетной записи.

Вопрос: я получил {"error": "access_denied", "error_description": "Invalid username or password."}, когда нажал кнопку аутентификации.

Ответ. Это сообщение об ошибке означает, что ваши учетные данные RDP недействительны. Пожалуйста, свяжитесь с вашим представителем Refinitiv, чтобы подтвердить свои учетные данные.

Вопрос. Я получил сообщение «ошибка 403», когда нажимаю кнопки запроса данных RDP.

Ответ: HTTP 403 (403 Forbidden) означает, что у вас нет разрешения на запрос данных. Пожалуйста, свяжитесь с представителем Refinitiv, чтобы подтвердить разрешение вашей учетной записи.

Заключение

С архитектурой разработки программного обеспечения приложение (или служба) больше не обращается только к серверам в своей серверной части. Ему необходимо подключаться к различным поставщикам услуг через Интернет, таким как облачное хранилище данных, веб-службы и т. д. Прокси-серверы и обратные прокси-серверы помогают приложению интегрироваться с различными службами и поставщиками данных.

В этом примере проекта показано, как интегрировать приложение веб-браузера в различные службы с обратным прокси-сервером. Клиентское приложение JavaScript может получать доступ к данным из различных служб, размещенных в разных местах, таких как Refinitiv Refinitiv Data Platform, Datastream Web Service, https://developers.refinitiv.com/en/api-catalog/refinitiv. -tick-history/refinitiv-tick-history-rth-rest-api и т. д. Однако этот пример реализации предназначен только для целей разработки и POC, а не для использования в производстве. Вы можете использовать сервер де-факто, такой как Nginx, для обратного прокси-сервера в вашей среде.

В то же время API Refinitiv Data Platform (RDP) предоставляют разработчикам различные данные и контент Refinitiv через простой в использовании веб-API. API-интерфейсы легко интегрируются в любое приложение и платформу, поддерживающую протокол HTTP и формат сообщений JSON.

Рекомендации

Для получения дополнительной информации, пожалуйста, ознакомьтесь со следующими ресурсами:

По любым вопросам, связанным с API Refinitiv Data Platform, обращайтесь на Форум RDP API на Странице вопросов и ответов сообщества разработчиков.

Гитхаб

Refinitiv-API-Примеры/Статья.RDP.JavaScript.HTTP-Прокси