При интеграции различных систем автоматизации с внешним оборудованием (например, с IP-телефонами, шлюзами или сторонними веб-сервисами) разработчики часто сталкиваются с необходимостью миграции готовых решений между разными средами разработки. В этой статье мы подробно рассмотрим, как перевести рабочий код отправки HTTP-запроса с авторизацией из современной платформы 1С 8.3 в проверенную временем среду Delphi 6.
Перенос кода из современной объектной модели 1С в Delphi 6 (выпущенную в далеком 2001 году) имеет свои архитектурные особенности. Мы разберем по шагам несколько надежных способов реализации этой задачи, включая обработку авторизации и работу со сторонними библиотеками.
Для начала давайте подробно проанализируем исходный код на стороне 1С, работу которого нам необходимо воспроизвести:
Соединение = Новый HTTPСоединение(ПараметрыТелефона.ip_Адрес_Телефона, ПараметрыТелефона.Port_Телефона, ПараметрыТелефона.Login_Телефона, ПараметрыТелефона.Password_Телефона);
Запрос = Новый HTTPЗапрос("servlet?number=" + НомерТелефона);
Ответ = Соединение.Получить(Запрос);
Выясним, какие механизмы здесь задействованы:
HTTPСоединение: Инициализирует сессию связи с сервером. В качестве параметров конструктор принимает IP-адрес хоста, порт, а также учетные данные (логин и пароль) для прохождения базовой аутентификации (Basic Authentication).HTTPЗапрос: Формирует структуру запроса. В конструктор передается относительный путь (URI) к обработчику на стороне телефона (сервлету) с GET-параметром number, содержащим номер телефона.Получить(): Выполняет синхронный GET-запрос по указанному адресу и возвращает объект ответа, из которого можно прочитать тело ответа и HTTP-статус.Наша главная задача в Delphi 6 — воссоздать этот функционал. Мы рассмотрим три различных подхода: использование стандартного набора компонентов Indy, работу через COM-объект MSXML и применение легковесной библиотеки Synapse.
---
Библиотека Indy (Internet Direct) поставляется вместе с Delphi 6 (обычно это версии Indy 8 или Indy 9). Главный компонент для работы с веб-протоколами в этой библиотеке — TIdHTTP. Он работает на блокирующих сокетах, что делает его структуру выполнения очень похожей на линейный код в 1С.
Рассмотрим пример реализации HTTP-запроса с авторизацией через TIdHTTP:
uses
SysUtils, Classes, IdHTTP, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient;
procedure SendPhoneRequestIndy(const IPAres, Port, Login, Password, PhoneNumber: string);
var
IdHTTP1: TIdHTTP;
URL: string;
ResponseText: string;
begin
IdHTTP1 := TIdHTTP.Create(nil);
try
// Настраиваем базовую авторизацию (Basic Authentication)
IdHTTP1.Request.BasicAuthentication := True;
IdHTTP1.Request.Username := Login;
IdHTTP1.Request.Password := Password;
// Формируем полный URL-адрес для запроса
// Шаблон: http://ip_address:port/servlet?number=phone_number
URL := 'http://' + IPAres + ':' + Port + '/servlet?number=' + PhoneNumber;
// Выполняем GET-запрос и получаем тело ответа
try
ResponseText := IdHTTP1.Get(URL);
// Здесь мы можем обработать успешный ответ от телефона
except
on E: Exception do
begin
// Обработка ошибок сети или авторизации
// Например: ShowMessage('Ошибка запроса: ' + E.Message);
end;
end;
finally
IdHTTP1.Free;
end;
end;
Важный нюанс: В старых версиях Indy свойства авторизации могут требовать явного указания заголовков или обработки события OnAuthorization. Если сервер (телефон) отклоняет учетные данные, попробуйте принудительно передать заголовок авторизации напрямую в свойства запроса или обновите библиотеку Indy до более стабильной сборки.
---
Если штатный компонент Indy в вашей сборке Delphi 6 работает нестабильно или вы не хотите перегружать приложение лишними визуальными компонентами, можно воспользоваться встроенным в операционную систему Windows механизмом через технологию OLE Automation. Для этого идеально подходит объект MSXML2.XMLHTTP.
Этот способ является наиболее лаконичным, надежным и не требует установки никаких дополнительных библиотек в Delphi 6. Он использует системную библиотеку Windows, которая автоматически обновляется вместе с операционной системой.
Проанализируем пример кода с использованием MSXML:
uses
ComObj, SysUtils;
procedure SendPhoneRequestMSXML(const IPAres, Port, Login, Password, PhoneNumber: string);
var
XmlHttp: OleVariant;
URL: string;
ResponseText: string;
begin
try
// Создаем OLE-объект Microsoft XMLHTTP
XmlHttp := CreateOleObject('MSXML2.XMLHTTP');
// Формируем URL
URL := 'http://' + IPAres + ':' + Port + '/servlet?number=' + PhoneNumber;
// Инициализируем GET-запрос.
// Параметры метода open:
// 1. Метод запроса ('GET')
// 2. Полный URL
// 3. Асинхронность (False означает, что запрос будет выполняться синхронно, как в 1С)
// 4. Имя пользователя для авторизации
// 5. Пароль
XmlHttp.open('GET', URL, False, Login, Password);
// Отправляем запрос
XmlHttp.send;
// Получаем текстовый ответ от сервера
ResponseText := XmlHttp.responseText;
// Проверяем HTTP-статус ответа (200 означает успех)
if XmlHttp.Status = 200 then
begin
// Успешно выполнено
end
else
begin
// Сервер вернул ошибку, например 401 (Unauthorized) или 404 (Not Found)
end;
except
on E: Exception do
begin
// Обработка системных ошибок (например, если хост недоступен)
end;
end;
end;
Использование MSXML2.XMLHTTP избавляет разработчика от необходимости ручной настройки заголовков базовой авторизации, так как библиотека берет эту рутину на себя.
---
Еще одна прекрасная альтернатива для Delphi 6 — бесплатная библиотека для работы с сетью Synapse. В отличие от Indy, она не имеет визуальных компонентов, не требует установки в палитру Delphi и состоит из обычных pas-файлов, которые достаточно просто подключить к проекту.
Для выполнения GET-запроса нам понадобится модуль httpsend. Давайте посмотрим, как выглядит отправка запроса в данном случае:
uses
SysUtils, Classes, httpsend;
procedure SendPhoneRequestSynapse(const IPAres, Port, Login, Password, PhoneNumber: string);
var
HTTP: THTTPSend;
URL: string;
ResponseList: TStringList;
begin
HTTP := THTTPSend.Create;
ResponseList := TStringList.Create;
try
// Заполняем учетные данные авторизации
HTTP.UserName := Login;
HTTP.Password := Password;
// Формируем URL
URL := 'http://' + IPAres + ':' + Port + '/servlet?number=' + PhoneNumber;
// Выполняем GET-запрос
if HTTP.HTTPMethod('GET', URL) then
begin
// Проверяем код состояния ответа
if HTTP.ResultCode = 200 then
begin
// Загружаем полученный поток в текстовый список
ResponseList.LoadFromStream(HTTP.Document);
// В переменной ResponseList.Text будет содержаться ответ от устройства
end;
end;
finally
ResponseList.Free;
HTTP.Free;
end;
end;
---
Очень часто современные IP-телефоны и REST-сервисы возвращают ответы в формате JSON. В Delphi 6 нет встроенных средств для работы с этим форматом данных (так как стандарт JSON появился позже релиза шестой версии среды). Однако мы можем изящно решить эту проблему двумя способами.
Мы можем использовать встроенный в Windows движок JScript для парсинга JSON без подключения внешних тяжелых библиотек:
uses
ComObj;
function GetValueFromJson(const JSONString, Key: string): string;
var
ScriptCtrl: OleVariant;
begin
Result := '';
try
ScriptCtrl := CreateOleObject('MSScriptControl.ScriptControl');
ScriptCtrl.Language := 'JScript';
// Добавляем JS-функцию парсинга и получения значения по ключу
ScriptCtrl.AddCode('function getValue(json, key) { var obj = eval("(" + json + ")"); return obj[key]; }');
Result := ScriptCtrl.Run('getValue', JSONString, Key);
except
// Обработка ошибок парсинга невалидного JSON
end;
end;
Для Delphi 6 отлично подходит сторонняя библиотека с открытым исходным кодом lkJSON (uLkJSON). Она написана на чистом Delphi и отлично компилируется в старых версиях среды. С ее помощью можно разбирать сложные древовидные структуры и массивы данных, получаемые в ответе на HTTP-запрос.
---
Мы рассмотрели три проверенных метода реализации HTTP-запросов в Delphi 6, аналогичных логике 1С 8.3: