четверг, 15 января 2015 г.

Делаем врезку

Активно занимаясь интеграцией приложений внутри компании научился многим интересным трюкам. Как, например, вставить формочку написанную ExtJs на страничку сайта?

Формочка представляет из себя полноценное одностраничное приложение. Отладка её выполняется в обычном режиме, когда файлы классов подгружаются по мере надобности. После "реализации хотелок" приложение минифицируется и отправляется на "боевой сервер". Приложение "генерится" и "билдится" при помощи Sencha Cmd 5.1.

Сайт, где форму видит конечный пользователь, имеет одно доменной имя. Сайт, где лежит код формы, имеет другое доменное имя. Сайт, который обрабатывает сведения формы, может иметь третье доменное имя. Физически все сервера разные.

Для врезки формочки на чужом сайте можно было бы использовать iframe, однако прежде чем отправить данные формочке нужно выпарсить некоторые сведения со страницы в которую она встроена. Поэтому создал контейнер, позади которого прицепил скрипт приложения и стили.

// контейнер
<div id="extjsapp"></div>

// стили
<link rel="stylesheet" type="text/css" href="https://myhost.ru/WarrantyForm-all.css" />

// формочка
<script type="text/javascript" src="https://myhost.ru/WarrantyForm/app.js"></script>


Sencha Cmd 5, создавая уменьшенную версию приложения, записывает в файл index.html так называемый микрозагрузчик, размещая его внутри тега head. Менять тег head на данном "урле" возможности не было, поэтому попытался поместить микрозагрузчик разными способами в целевую страницу. Пробовал менять параметры в app.json. Пробовал просто вставлять весь микролоадер в текст страницы, но всё безуспешно. Сервера разные, в браузере ошибка.

Спешу обрадовать. Есть очень простое решение. Нужно создать пару неймспейсов и всё заработает. Выглядит решение так:

// контейнер
<div id="extjsapp"></div>

// стили
<link rel="stylesheet" type="text/css" href="https://myhost.ru/WarrantyForm-all.css" />

// неймспейсы
<script>
Ext = window.Ext || {}; Ext.Boot={};
</script>

// формочка
<script type="text/javascript" src="https://myhost.ru/WarrantyForm/app.js"></script>


 Решение предложено в этой ветке форума.

 Поскольку в подобной ситуации используются кросдоменные AJAX-запросы, то не могу не упомянуть о трюке с заголовком Access-Control-Allow-Origin. Дело в том, что сервер Apache может разрешить такой режим работы только одному сайту. Чтобы отобразить формочку на нескольких сайтах существует такой остроумный приём:

SetEnvIf Origin "^(http://myhost1\.ru|https://myhost2\.ru|null)$" origin_is=$0

Header  set Access-Control-Allow-Origin %{origin_is}e env=origin_is


Имя хоста, которое пришло в запросе браузера в хедере Origin, сверяется со списком внутри регулярного выражения. Если есть совпадение, оно попадает в некую созданную нами переменную окружения origin_is. Сервер пишет в ответе в Access-Control-Allow-Origin нужный хост из переменно origin_is.

Чтобы работать из браузера с JIRA мне ещё  нужно было добавить в конфиг Apache следующее:

Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Custom-Header"
Header set Access-Control-Allow-Credentials "true"
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"