Прокси-контроллер
Прокси-контроллер служит прослойкой между внешней системой и виджетом отчета HCCP. Он проверяет параметры, переданные из виджета, и передает их в бэкенд HCCP, добавляя к ним заголовок аутентификации и другие данные, необходимые для работы стыковки.
Для логина (POST /login
) необходимо реализовать метод, который будет передавать учетные данные в API HCCP. Пример реализации на Ruby:
def login request_params = { url: URI.join(config.url, '/api/login').to_s, method: :post, payload: { params: { login: config.login, password: config.password } }.to_json } render json: RestClient::Request.execute(request_params) end
В результате метод должен вернуть фронтэнду полученный от API HCCP json.
Для остальных GET
запросов запросов необходимо просто проксировать запросы. Для POST
запросов необходимо добавлять hccp_auth_token
. Пример прокси контроллера:
around_filter :proxy_error def proxy method = request.method.downcase.to_sym result = request_widget_backend(params[:path], method, permitted_params) if method == :put if result head :no_content else head :bad_request end else render json: result end end def request_widget_backend(path, method = :get, parameters = {}) request_params = if method == :get { method: :get, url: URI.join(config.url, path).to_s, headers: { params: parameters } } else { method: method, url: "#{URI.join(config.url, path)}?hccp_auth_token=#{params[:hccp_auth_token]}", payload: parameters.to_json } end RestClient::Request.execute(request_params) end def proxy_error yield rescue RestClient::Exception => e render json: e.response, status: e.response.code end private def permitted_params params.symbolize_keys.except(*service_params) end def service_params %i[controller action path format] end
ВАЖНО: В случае ошибки выполнения запроса необходимо возвращать код ошибки, как это сделано в методе proxy_error
, чтобы в случае, если, например, истек срок действия токена, то виджет заново аутентифицировался.
Встраивание JS
После загрузки JS и CSS из HCCP выполняется инициализация виджета данными приложения и сущности, после чего вызывается функция render()
.
Параметры, передаваемые в функцию render()
:
Имя | Значение (пример) | Обязательный |
---|---|---|
baseURL | URL по которому виджет выполняет запросы, может быть как полным адресом В первом случае виджет будет выполнять запросы к Во втором случае – | Нет |
locale | Язык, с которым будет инициализирован виджет (' ru') | Нет |
customerId | id абонента, которые должен отображаться в виджете | Да |
containerId | id элемента, в котором отобразится виджет('customer-widget-id') | Да |
Ниже приведен пример встраивания виджета в веб-страницу:
!!! %html %head %script{type: "text/javascript", src: "http://localhost:3000/customerWidget.js"} %link{rel: 'stylesheet', type: "text/css", href: "http://localhost:3000/customerWidget.css"} %body %div %h1 Welcome %p #customer-widget-id{style: 'width: 1000px; margin: 0 auto; font-size: 13px; border: 5px dashed lightgrey;'} :javascript document.addEventListener('DOMContentLoaded', () => { HCCPCustomerWidget.render({ baseURL: '/hccp/', locale: 'ru', customerId: '50162901', containerId: 'customer-widget-id', }); });
Пример замены виджета с пользовательскими шаблонами на виджет абонента
В случае с хопером, нам не нужно беспокоиться по поводу прокси-контроллера: здесь все уже реализовано.
Достаточно сделать следующие шаги:
Заменяем подгрузку виджета пользовательских шаблонов на подгрузку виджета абонента
[sergeichukd@mbp ~/dev/hoper (master *)]$ git diff app/views/layouts/admin.haml diff --git a/app/views/layouts/admin.haml b/app/views/layouts/admin.haml index 85f9a5b74..77e19df44 100644 --- a/app/views/layouts/admin.haml +++ b/app/views/layouts/admin.haml @@ -15,8 +15,8 @@ :javascript window.HBWidgetOptions = #{hbw_options.to_json.html_safe} - if Hoper::Config.widgets.hccp_reports.try(:public_url) - = javascript_include_tag URI.join(Hoper::Config.widgets.hccp_reports.public_url, 'reportsWidget.js') - = stylesheet_link_tag URI.join(Hoper::Config.widgets.hccp_reports.public_url, 'reportsWidget.css') + = javascript_include_tag URI.join(Hoper::Config.widgets.hccp_reports.public_url, 'customerWidget.js') + = stylesheet_link_tag URI.join(Hoper::Config.widgets.hccp_reports.public_url, 'customerWidget.css') :javascript var alertGroups = #{Hoper::Config.interface.alert_groups?}; var UI = {}; [sergeichukd@mbp ~/dev/hoper (master *)]$
После этого подменяем рендер виджета пользовательских шаблонов на рендер виджета абонента
[sergeichukd@mbp ~/dev/hoper (master *)]$ git diff app/views/reports/custom/index.haml diff --git a/app/views/reports/custom/index.haml b/app/views/reports/custom/index.haml index 2d418136d..3b20fa83e 100644 --- a/app/views/reports/custom/index.haml +++ b/app/views/reports/custom/index.haml @@ -1,12 +1,13 @@ %h1.header=t('menu.reports.custom') -.custom-reports-styles(id="custom-reports-index") +#customer-widget-id{style: 'width: 1000px; margin: 0 auto; font-size: 13px; border: 5px dashed lightgrey;'} :javascript (function() { - HCCPReportsWidget.render({ - baseURL: '/hccp/', - locale: "#{locale.to_s}", - containerId: 'custom-reports-index' + HCCPCustomerWidget.render({ + baseURL: '/hccp/', + locale: 'ru', + customerId: '50162901', + containerId: 'customer-widget-id', }); }).call(this); [sergeichukd@mbp ~/dev/hoper (master *)]$
В конфиге хопера задаем параметры виджета hccp_reports:
hccp_reports: public_url: 'http://localhost:4000' url: 'http://localhost:4000' login: 'gordon' password: 'q123'
Конфигурируем unicorn на 8 воркеров (для корректной работы виджета нужно более 4 воркеров, так как виджет делает несколько параллельных запросов к апи хопера)
unicorn: pid: tmp/unicorn.pid socket: 3000 workers: 8 max_memory_size_mb: 300 request_timeout_seconds: 600 serve_static_assets: true
После этого подниаем hccp на 4000 порту
Поднимаем хопер в продакшн моде командой
bundle exec unicorn -E production -c config/unicorn.rb
В результате, если открыть хопер и перейти в "Отчеты" -> "Пользовательские отчеты", то должна отрисоваться такая страница