TIdHTTPProxyServer, вызывающий исключение RSHTTPUnknownProtocol "Неизвестный протокол" - PullRequest
0 голосов
/ 27 мая 2019

Я перекодирую старую программу Delphi XE, используя Delphi 10.3 Rio. Он использует прослушивание компонента TIdHTTPProxyServer Indy на 127.0.0.1:80.

  with IdHTTPProxyServer.Bindings.Add do begin

    IP := '127.0.0.1';
    Port := 80;

  end;

  IdHTTPProxyServer.Active := True;

Для тестирования я добавил 127.0.0.1 localtest123.com и 127.0.0.1 www.localtest123.com в файл hosts и отключил службу кэширования DNS. Затем в нескольких браузерах я запросил http://localtest123.com/ и http://www.localtest123.com/. С помощью OutputDebugString () я могу видеть принятые соединения, но затем возникает ошибка «Неизвестный протокол».

Я отладил исключение в процедуре TIdHTTPProxyServer.CommandPassThrough в IdHTTPProxyServer.pas. Кажется, что LURI.Protocol - пустая строка, поэтому RSHTTPUnknownProtocol вызывается.

  LContext := TIdHTTPProxyServerContext(ASender.Context);
  LContext.FCommand := ASender.CommandHandler.Command; //<-'GET'
  LContext.FTarget := ASender.Params.Strings[0]; //<-'/'

  LContext.FOutboundClient := TIdTCPClient.Create(nil);
  try
    LURI := TIdURI.Create(LContext.Target); //<-'/'
    try
      TIdTCPClient(LContext.FOutboundClient).Host := LURI.Host; //<-''

      if LURI.Port <> '' then begin //<-''
        TIdTCPClient(LContext.FOutboundClient).Port := IndyStrToInt(LURI.Port, 80);
      end
      else if TextIsSame(LURI.Protocol, 'http') then begin //<-''    {do not localize}
        TIdTCPClient(LContext.FOutboundClient).Port := IdPORT_HTTP;
      end
      else if TextIsSame(LURI.Protocol, 'https') then begin //<-'' {do not localize}
        TIdTCPClient(LContext.FOutboundClient).Port := IdPORT_https;
      end else begin
        raise EIdException.Create(RSHTTPUnknownProtocol);
      end;

Я, вероятно, что-то упускаю, но TIdHTTPProxyServer просто работает без большого количества кода, поэтому мне нужно обратиться за помощью по этому исключению. Заранее спасибо!

1 Ответ

1 голос
/ 27 мая 2019

Вы не можете просто перенаправить домены в вашем файле HOSTS и ожидать, что все будет работать волшебным образом.Это не то, как работает прокси.

Вы должны явно настроить веб-браузеры для отправки HTTP-запросов через HTTP-прокси, чтобы они форматировали правильные запросы, понятные прокси.Отправка HTTP-запроса напрямую на целевой веб-сервер обрабатывается иначе, чем отправка того же HTTP-запроса через прокси.

Вы получаете исключение, поскольку запросы браузера не нацелены на ваш прокси должным образом.

Например, когда браузер отправляет запрос HTTP GET непосредственно на целевой веб-сервер, он подключается непосредственно к этому серверу, а затем отправляет запрос, который выглядит примерно так:

GET /path HTTP/1.1
Host: server.com

Но когдаон отправляет тот же запрос через HTTP-прокси, подключается к прокси-серверу и отправляет запрос, который выглядит следующим образом:

GET http://server.com/path HTTP/1.1

В вашем браузере отсутствует дополнительная информация о пути в строке GETзапросов, поскольку у вас не настроены браузеры для прокси, поэтому исключение, когда TIdHTTPProxyServer пытается определить информацию, необходимую для подключения к целевому веб-серверу, и перенаправить на него текущий запрос.

Это в основном то, как работает HTTP, и как TIdHTTPProxyServer предназначен дляработа.

Когда HTTPS задействован, все немного сложнее, но я пока опускаю эту деталь, поскольку она не имеет отношения к вашему вопросу об исключении.

ОБНОВЛЕНИЕ : в комментариях вы говорите:

В версии XE никогда не возникало исключение при проверке протокола, который все еще работает сегодня, потому что я вручную установил хост и порт в DoHTTPBeforeCommand.

В этой старой версии исключений не возникало, поскольку TIdHTTPProxyServer еще не проверял протокол, чтобы различать HTTP и HTTPS.Вы смогли вручную заполнить недостающую информацию при получении запроса, который не был специально нацелен на ваш прокси.Вот почему у вас все работало раньше.

В более поздней версии TIdHTTPProxyServer был обновлен, чтобы различать HTTP и HTTPS, когда в запросе явно не указан порт, поэтому порт по умолчанию устанавливается на основе запрошенного протокола.Эта проверка происходит до вызова DoHTTPBeforeCommand().

Чтобы вернуть старое поведение, вам придется изменить исходный код TIdHTTPProxyServer, чтобы отложить возникновение исключения до тех пор, пока не вернется DoHTTPBeforeCommand(), поэтомуу вас есть шанс снова заполнить пропущенные значения.

Если вы подаете запрос на добавление функции , я мог бы рассмотреть вопрос о добавлении его в официальный код Indy.

...