HTTP-сервисы появились в платформе 8.3.5 и с тех пор начали активно развиваться. С их помощью можно реализовать обмен данными без использования COM. Или создать какой-нибудь frontend для информационной базы.
В данной статье я опишу frontend, использующий JQuery и AJAX запросы. Все объекты можно создавать как непосредственно в самой конфигурации, так и в расширении.
Итак, приступим. Вначале создадим объект конфигурации HTTP-сервис, укажем корневой URL, например, front
В нем создадим 5 шаблонов URL и методы к ним:
- Старт - для инициализации начальной страницы; шаблон /index; HTTP-метод GET
Свойства метода "Получить" шаблона "Старт"
- JS - для получения JavaScript'ов для страницы; шаблон /js; HTTP-метод GET
- CSS - для стилей для страницы; шаблон /css; HTTP-метод GET
- JQuery - для подключения библиотеки JQuery; шаблон /jquery; HTTP-метод GET
- ajax - для вызова; шаблон /ajax; HTTP-метод POST
Свойства метода "МетодAJAX" шаблона "ajax"
Тексты скриптов JS, описание стилей CSS, библиотеку JQuery (Скачать) и начальную страницу HTML поместим в макеты обработки HTTP_ОбработкаСервиса. Процедуры для обработки запросов поместим в менеджер этой обработки.
Добавим экспортную функцию ПолучитьНачальнуюСтраницу() в модуль менеджера для загрузки начальной страницы
Функция ПолучитьНачальнуюСтраницу() Экспорт
возврат ПолучитьМакет("НачальнаяСтраница").ПолучитьТекст();
КонецФункции
Функция ОбработатьЗапросAjax(СтруктураJSON) Экспорт
Контент="Вы ввели <b>"+
СтруктураJSON.t+
"</b>";
возврат Контент;
КонецФункции
Заполним макеты:
Макет НачальнаяСтраница может иметь тип ТекстовыйТекумент, а может, как в данном случае, и HTTMДокумент.
(в тексте для публикации пришлось заменить onclick= на _onclick_=, иначе редактор просто удалял этот фрагмент. При копировании кода нужно убрать выделение знаками "_")
Макет "НачальнаяСтраница"
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;">
<script type="text/javascript" src="./jquery"></script>
<script type="text/javascript" src="./js"></script>
<link rel="stylesheet" href="./css" type="text/css">
</head>
<body>
<p>Проверка</p>
Введите имя<input type="text" id="e_name">
<button type="submit"
id="okButton"
style="top: 8px; left: 0px; height: 21px; width: 80px;"
_onclick_="GetContent(this)">
OK
</button>
<div id="content">
Контент
</div>
</body>
</html>
В макет JS включим скрипты для обработки логики нашего front'a
var cur_url=""; //Переменная для хранения корневого адреса страницы
//--------Инициализация
$(document).ready(function(){
cur_url=document.location.href.substring(0, document.location.href.lastIndexOf("/"));
})
//--------------Функции--------------------
function GetContent(th)
{
$.ajax({
type: "POST",
url: cur_url+"/ajax",
data: JSON.stringify({action: "test", t: $("#e_name").val()}),
cache: false,
success: function(html){
$("#content").html(html);
}
});
}
Теперь перейдем в модуль HTTP-Сервиса и создадим обработчики методов Получить, ПолучитьJS, ПолучитьСSS, ПолучитьJQuery и МетодAJAX:
Функция СтартПолучить(Запрос)
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(Обработки.HTTP_ОбработкаСервиса.ПолучитьНачальнуюСтраницу());
Возврат Ответ;
КонецФункции
Функция JSПолучитьJS(Запрос)
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(Обработки.HTTP_ОбработкаСервиса.ПолучитьМакет("JS").ПолучитьТекст());
Возврат Ответ;
КонецФункции
Функция CSSПолучитьСSS(Запрос)
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(Обработки.HTTP_ОбработкаСервиса.ПолучитьМакет("CSS").ПолучитьТекст());
Возврат Ответ;
КонецФункции
Функция JQueryПолучитьJQuery(Запрос)
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(Обработки.HTTP_ОбработкаСервиса.ПолучитьМакет("JQuery").ПолучитьТекст());
Возврат Ответ;
КонецФункции
Функция ajaxМетодAJAX(Запрос)
ТелоЗапроса = Запрос.ПолучитьТелоКакСтроку();
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ТелоЗапроса);
СтруктураJSON = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(Обработки.HTTP_ОбработкаСервиса.ОбработатьЗапросAjax(СтруктураJSON));
Возврат Ответ;
КонецФункции
Сохраняем конфигурацию (расширение).
Теперь необходимо опубликовать наш HTTP-сервис
Пример файла публикации default.vrd
<?xml version="1.0" encoding="UTF-8"?>
<point xmlns="http://v8.1c.ru/8.2/virtual-resource-system"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
base="/demo"
ib="File="C:\Users\Admin\Documents\Базы\Demo";Usr=web;Pwd=123;"
enable="false"
allowexecutescheduledjobs="">
<httpServices publishExtensionsByDefault="true">
<service name="HTTP_Front"
rootUrl="front"
enable="true"
reuseSessions="autouse"
sessionMaxAge="200"
poolSize="10"
poolTimeout="50"/>
</httpServices>
<standardOdata enable="false"
reuseSessions="autouse"
sessionMaxAge="20"
poolSize="10"
poolTimeout="5"/>
</point>
Перезапускаем веб сервер и набираем в адресной строке http://127.0.0.1/demo/hs/front/index. Произойдут следующие действия:
- 1С выполнит СтартПолучить и вернет текст начальной страницы
- Браузер при загрузке страницы обнаружит, что нужно загрузить еще три ссылки http://127.0.0.1/demo/hs/front/jquery, http://127.0.0.1/demo/hs/front/js и http://127.0.0.1/demo/hs/front/css и передаст вызовы 1С через веб сервер
- 1С выполнит методы JQueryПолучитьJQuery, JSПолучитьJS, CSSПолучитьСSS и вернет содержание браузеру.
- Страница полностью загрузится
Теперь на полученной веб-странице введем значение в поле и нажмем кнопку Ок. Начнется выполнение ajax-запроса и 1С вернет какой-нибудь контент, который включиться в содержимое блока <div id="content"> без полной перезагрузки страницы.
Хочу отметить, что во время разработки и отладки после каждого сохранения, необходимо перезапускать веб-сервер, чтобы он перечитал конфигурацию. Упростить это можно, заменив на время вызов внешней обработки из модуля HTTP-Сервиса, правда придется использовать не модуль менеджера, а модуль объекта. Но это мелочи.
Бонусом опубликую php-скрипт, который кэширует запросы, тем самым минимизирует обращения напрямую к информационной базе
<?php
$url="http://127.0.0.1/demo/hs/front/index";
$cache_path="/var/www/html/cache";
$history = 2;
//ini_set('display_errors',1);
//error_reporting(E_ALL);
$path = substr($url, 0, strrpos( $url, '/'));
if (count($_POST)==0){
//$html = file_get_contents($url);
$html=get_extfile('./index', $path, $cache_path);
$url_js=array();
$dom = new DOMDocument;
$dom->loadHTML($html);
$scripts = $dom->getElementsByTagName('script');
foreach ($scripts as $script) {
$name_s = $script->getAttribute('src');
$text_s = get_extfile($name_s,$path,$cache_path);
if($name_s=='./js.js') $text_s = str_replace('/ajax','/index.php',$text_s);
$s= $dom->createTextNode($text_s);
$script->removeAttribute('src');
$script->appendChild($s);
}
$links = $dom->getElementsByTagName('link');
$head= $dom->getElementsByTagName('head');
foreach ($links as $l)
if ($l->getAttribute('type')=='text/css')
{
$name_s = $l->getAttribute('href');
$text_s = get_extfile($name_s,$path,$cache_path);
$s = $dom->createTextNode($text_s);
$style=$dom->createElement('style');
$style->appendChild($s);
$head->item(0)->appendChild($style);
$l->setAttribute('href','');
}
$html = $dom->saveHTML();
//echo($url_js);
echo($html);
die();
}
$query=file_get_contents('php://input');
$query_file=$cache_path."/".hash('md5',$query);
$rasd='$%@#';
$new_cache=false;
$now = time();
$use_cache = (strripos($query,'nocache') === false) ? true : false ;
if ($use_cache){
if (!file_exists($query_file)) $new_cache=true;
else
if ($now - filemtime($query_file) >= 60 * 60 * $history ) $new_cache=true;
} else $new_cache=true;
if (!$new_cache)
{
$fp = fopen($query_file, "r");
$contents = fread($fp, filesize($query_file));
fclose($fp);
$data=explode($rasd,$contents);
//$data=preg_split($contents,$rasd);
if ($data[0]==$query)
{
$response=$data[1];
}
else $new_cache=true;
}
if ($new_cache)
{
$ch = curl_init($path . '/ajax');
// устанавлваем даные для отправки
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
// флаг о том, что нужно получить результат
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// отправляем запрос
$response = curl_exec($ch);
// закрываем соединение
curl_close($ch);
if ($use_cache)
{
$fp = fopen($query_file, "w");
// записываем в файл текст
fwrite($fp,$query.$rasd.$response);
// закрываем
fclose($fp);
}
}
echo($response);
function get_extfile($name, $path, $cache_path)
{
$ext_file = $path . str_replace('./','/',$name);
$cache_file=$cache_path ."/". str_replace('./','/',$name);
$new_cache=false;
$now = time();
$history = 2;
if (!file_exists($cache_file)) $new_cache=true;
else
if ($now - filemtime($cache_file) >= 60 * 60 * $history ) $new_cache=true;
if (!$new_cache)
{
$fp = fopen($cache_file, "r");
$text = fread($fp, filesize($cache_file));
fclose($fp);
return $text;
}
$text=file_get_contents($ext_file);
$fp = fopen($cache_file, "w");
// записываем в файл текст
fwrite($fp,$text);
// закрываем
fclose($fp);
return $text;
}
?>