我正在使用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可以在没有太多代码的情况下正常工作,因此我不得不就此异常寻求帮助。预先感谢!
答案 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的官方代码中。