TIdHTTPProxyServer引发“未知协议” RSHTTPUnknownProtocol异常

时间:2019-05-27 03:00:49

标签: delphi indy indy10 delphi-10.3-rio

我正在使用Delphi 10.3 Rio重新编码一个旧的Delphi XE程序。它使用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,并禁用了DNS缓存服务。然后在多个浏览器中,我请求了http://localtest123.com/http://www.localtest123.com/。使用OutputDebugString(),我可以看到已接受的连接,但是会引发“未知协议”错误。

我在IdHTTPProxyServer.pas的TIdHTTPProxyServer.CommandPassThrough过程中调试了该异常。看起来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 个答案:

答案 0 :(得分:1)

您不能只重定向HOSTS文件中的域,并期望一切都能正常进行。那不是代理的工作原理。

您必须显式配置Web浏览器以通过HTTP代理发出HTTP请求,以便它们格式化代理可以理解的正确请求。将HTTP请求直接发送到目标Web服务器的方式与通过代理发送相同HTTP请求的方式不同。

由于浏览器请求未正确定位到您的代理,因此您会收到例外。

例如,当浏览器直接向目标Web服务器发送HTTP GET请求时,它将直接连接到该服务器,然后发送如下所示的请求:

GET /path HTTP/1.1
Host: server.com

但是,当它通过HTTP代理发送相同的请求时,它将连接到代理并发送一个看起来更像这样的请求:

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

浏览器请求中缺少GET行中的多余路径信息,因为您没有为代理配置浏览器,因此TIdHTTPProxyServer试图确定所需信息时会出现异常与目标Web服务器建立连接并将当前请求转发给它。

从根本上讲,这与HTTP的工作方式以及TIdHTTPProxyServer的工作方式一样。

当涉及到HTTPS时,事情要复杂一些,但是我暂时不再赘述,因为它与您有关异常的问题无关。

更新:在评论中,您说:

  

在XE版本中,当我检查协议仍然可以使用时,它从未引发异常,因为我已经在DoHTTPBeforeCommand中手动设置了主机和端口。

在该旧版本中,没有引发异常,因为TIdHTTPProxyServer尚未检查协议以区分HTTP和HTTPS。当收到不是专门针对您的代理的请求时,您可以手动填写缺少的信息。这就是为什么事情之前对您有用。

在更高版本中,TIdHTTPProxyServer已更新,以在请求中未明确指定端口时区分HTTP和HTTPS,因此将根据请求的协议设置默认端口。该检查发生在调用DoHTTPBeforeCommand()之前。

要恢复原来的行为,您必须更改TIdHTTPProxyServer的源代码以将引发异常的时间推迟到DoHTTPBeforeCommand()返回之后,这样您才有机会填写缺失的值再次。

如果您为此file a feature request,我可能会考虑将其添加到Indy的官方代码中。