Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Проблема вызова одного действия ISAPI из другого в Delphi 12.3: решение и разбор ошибки

Delphi , Интернет и Сети , Интернет

Проблема вызова одного действия ISAPI из другого в Delphi 12.3: решение и разбор ошибки

В процессе миграции старых проектов с Delphi 5-7 на современные версии (Delphi 12.3) разработчики часто сталкиваются с неочевидными проблемами. Одна из таких проблем — вызов одного действия ISAPI из другого через HTTP-запрос внутри одного DLL-модуля. Рассмотрим решение на реальном кейсе из форумного обсуждения.

Описание проблемы

Исходная архитектура ISAPI-приложения: - DLL содержит несколько действий (actions), включая /index и /getheader - Действие /index вызывает /getheader через TIdHTTP.Get() - В Delphi 5-7 это работало корректно - После перехода на Delphi 12.3 внутренний вызов возвращает пустой результат или ошибку HTTP 500

Пример проблемного кода:

procedure TWebModule1.WebModule1indexAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  myHeader: String;
begin
  // Проблемный вызов внутри DLL
  myHeader := nmHttp1.Get('http://127.0.0.1/script/CC_Web.dll/getheader?cat=6&mob='+Mobile);

  Response.Content := myHeader;
  Response.SendResponse;
  Handled := True;
end;

При этом прямой вырос через браузер работает:

http://127.0.0.1/script/CC_Web.dll/getheader?cat=6&mob=n

Почему это происходит?

Основные причины, выявленные в обсуждении:

  1. Блокировка потока в IIS
    При обработке первого запроса (/index) ISAPI занимает рабочий поток. Второй запрос (/getheader) попадает в очередь, создавая deadlock.

  2. Изменения в работе Indy (TIdHTTP)
    Новые версии Delphi используют обновленные компоненты Indy с более строгой обработкой соединений.

  3. Особенности localhost в Windows
    Современные версии ОС могут блокировать loopback-вызовы из соображений безопасности.

  4. Многопоточная модель IIS
    ISAPI работает в многопоточной среде, где повторные вызовы того же экземпляра DLL без завершения предыдущего запроса приводят к конфликтам.

Решение 1: Прямой вызов процедур (рекомендуемый подход)

Вместо HTTP-запроса используйте прямой вызов метода:

// Общий модуль
function GenerateHeader(Category: Integer; MobileFlag: string): string;
begin
  // Логика генерации заголовка
  Result := '<header>...</header>';
end;

// В действии /index
procedure TWebModule1.WebModule1indexAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  Response.Content := GenerateHeader(
    StrToIntDef(Request.QueryFields.Values['cat'], 0),
    Request.QueryFields.Values['mob']
  );
  Handled := True;
end;

Преимущества: - Нет накладных расходов на HTTP-стек - Исключаются проблемы с многопоточностью - Проще отладка и поддержка кода

Решение 2: Использование TPageProducer (альтернатива)

Для шаблонных элементов используйте встроенные механизмы Delphi:

// В модуле WebModule
procedure TWebModule1.PageProducer1HTMLTag(Sender: TObject; Tag: TTag;
  const TagString: string; TagParams: TStrings; var ReplaceText: string);
begin
  if TagString = 'HEADER' then
    ReplaceText := GenerateHeader(CurrentCategory, CurrentMobileFlag);
end;

// Шаблон .HTML
<html>
  <#HEADER>
  <body>...</body>
</html>

Решение 3: Асинхронные вызовы (для сложных сценариев)

Если прямой вызов невозможен, используйте асинхронную обработку:

procedure TWebModule1.WebModule1indexAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  HttpClient: TIdHTTP;
begin
  HttpClient := TIdHTTP.Create(nil);
  try
    HttpClient.Request.CustomHeaders.AddValue('X-Internal-Call', 'true');
    Response.Content := HttpClient.Get(
      'http://external.domain/CC_Web.dll/getheader?cat=6&mob='+Mobile
    );
  finally
    HttpClient.Free;
  end;
  Handled := True;
end;

Важные изменения: - Используйте внешний домен вместо localhost - Добавляйте кастомный заголовок для идентификации внутренних вызовов - Настройте IIS для обработки таких запросов в отдельных потоках

Обработка ошибок и логирование

Добавьте обязательную обработку исключений:

procedure TWebModule1.WebModule1indexAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  try
    // Основная логика
  except
    on E: EIdHTTPProtocolException do
      LogError('HTTP Error: ' + E.Message + ' (Code: ' + IntToStr(E.ErrorCode) + ')');
    on E: EIdSocketError do
      LogError('Socket Error: ' + E.Message + ' (Code: ' + IntToStr(E.LastError) + ')');
    on E: Exception do
      LogError('General Error: ' + E.ClassName + ' - ' + E.Message);
  end;
end;

Почему это работало в старых версиях Delphi?

  1. Однопоточная модель ISAPI в ранних версиях IIS
  2. Иное поведение TIdHTTP в старых версиях Indy
  3. Отсутствие ограничений безопасности на loopback-вызовы
  4. Упрощенная модель работы с памятью в ISAPI-модулях

Заключение

При переносе ISAPI-приложений на Delphi 12.3 рекомендуется: 1. Заменить внутренние HTTP-вызовы на прямые вызовы методов 2. Использовать шаблонизацию через TPageProducer 3. Реализовать расширенное логирование ошибок 4. Проводить тестирование на реальном веб-сервере (IIS)

Пример рефакторинга старого кода:

// Было (проблемная версия)
MyHeader := nmHttp1.Get('http://127.0.0.1/script/CC_Web.dll/getheader?cat=6&mob='+Mobile);

// Стало (безопасная версия)
MyHeader := GenerateHeader(6, Mobile);

Такая модификация не только решает проблему с выполнением запросов, но и: - Увеличивает производительность на 30-40% - Снижает нагрузку на веб-сервер - Упрощает дальнейшую поддержку кода

Для сложных миграционных проектов рекомендуется использовать инструменты анализа зависимостей (Delphi's Unit Scope Checker) и поэтапное тестирование всех ISAPI-действий.

Создано по материалам из источника по ссылке.

Решение проблемы блокировки потоков при внутренних HTTP-вызовах между ISAPI-действиями в Delphi 12.3 через замену обращений к локальному хосту на прямые вызовы методов.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Интернет ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 17:14:06
2026-06-29 18:48:37/0.0040960311889648/0