gpt4 book ai didi

delphi - TIdHTTPProxyServer 引发 "Unknown Protocol"RSHTTPUnknownProtocol 异常

转载 作者:行者123 更新时间:2023-12-04 17:37:02 24 4
gpt4 key购买 nike

我正在使用 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() 我可以看到已接受的连接,但随后会引发“未知协议(protocol)”错误。

我调试了 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 不需要太多代码就可以工作,所以我不得不寻求有关此异常的帮助。提前致谢!

最佳答案

您不能只重定向 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 时,事情会稍微复杂一些,但我暂时不考虑这个细节,因为它与您关于异常的问题无关。

更新:在评论中,您说:

In the XE version it never raised an exception when checking for the protocol which would still work today because I manually set the host and port in DoHTTPBeforeCommand.

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

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

要恢复旧行为,您必须更改 TIdHTTPProxyServer 的源代码以延迟引发异常,直到 DoHTTPBeforeCommand() 返回之后,因此您有机会再次填补缺失值。

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

关于delphi - TIdHTTPProxyServer 引发 "Unknown Protocol"RSHTTPUnknownProtocol 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56319180/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com