使用 Indy 对 IP-based 主机的 HTTP 获取请求

HTTP Get request to IP-based host using Indy

我有一些 Delphi 连接到 servlet 的代码,我正在尝试从 TIdTCPClient 切换到 TIdHTTP。

我这样连接到servlet

   try
      lHTTP := TIdHTTP.Create( nil );
      responseStream := TMemoryStream.Create;
      lHTTP.Get(HttpMsg, responseStream);
      SetString( html, PAnsiChar(responseStream.Memory), responseStream.Size);
      AnotarMensaje( odDepurar, 'IMPFIS: Impresora fiscal reservada ' + html );

其中 HttpMsg 是 localhost:6080/QRSRPServer/PedirImpresion?usuarioDMS=hector

我得到的只是

GET localhost:6080/QRSRPServer/PedirImpresion?usuarioDMS=hector HTTP/1.1
Content-Type: text/html
Accept: text/html, */*
User-Agent: Mozilla/3.0 (compatible; Indy Library)

HTTP/1.1 400 Bad Request

我之前的HTTP对话框是这样的

GET /QRSRPServer/PedirImpresion?usuarioDMS=hector HTTP/1.1
Host: localhost:6080

HTTP/1.1 200 OK

因此,我尝试添加主机 header,此主机为:localhost:6080

   try
      lHTTP := TIdHTTP.Create( nil );
      lHTTP.Host := Host;
      responseStream := TMemoryStream.Create;
      lHTTP.Get(HttpMsg, responseStream);
      SetString( html, PAnsiChar(responseStream.Memory), responseStream.Size);
      AnotarMensaje( odDepurar, 'IMPFIS: Impresora fiscal reservada ' + html );

然后我得到

Socket Error # 11004

这比我想象的要容易。我假设有一个包含端口的 "host" 参数就足够了,但是查看 Wireshark 捕获我发现它正在通过标准 HTTP 端口发送所有内容。

所以这成功了

try
  lHTTP := TIdHTTP.Create( nil );
  lHTTP.Host := GatewayIp;
  lHTTP.Port := GatewayPuerto;
  responseStream := TMemoryStream.Create;
  lHTTP.Request.CustomHeaders.Clear;
  lHTTP.Request.CustomHeaders.Add('Host: ' + Host );
  lHTTP.Get(HttpMsg, responseStream);
  SetString( html, PAnsiChar(responseStream.Memory), responseStream.Size);
  AnotarMensaje( odDepurar, 'IMPFIS: Impresora fiscal reservada ' + html );

Where HttpMsg is localhost:6080/QRSRPServer/PedirImpresion?usuarioDMS=hector

HttpMsg 必须http://https://:

开头
http://localhost:6080/QRSRPServer/PedirImpresion?usuarioDMS=hector

TIdHTTP 解析 URL 并发现缺少的协议方案时,您应该得到一个 EIdUnknownProtocol 异常。

TIdHTTP 应该始终发送 Host header,但尤其是对于 HTTP 1.1 请求,但您声称不是。这就是您收到 Bad Request 错误的原因,因为 HTTP 1.1 服务器需要拒绝省略 header.

的 HTTP 1.1 请求

您还声称 TIdHTTPGET 行中包含主机和端口值。 ONLY 一次是通过 HTTP 代理连接到主机时,但我根本没有看到您配置 TIdHTTP.ProxyParams 属性。

简而言之,TIdHTTP 不应该像您声称的那样行事。

正确的解决方案是确保将 完整 URL 传递给 TIdHTTP.Get().

附带说明一下,您的代码要求 htmlAnsiString。您应该将其更改为标准 string(在 D2007 及更早版本中为 AnsiString)并让 TIdHTTP return 为您提供 string,然后您就不会不再需要 TMemoryStream

html := lHTTP.Get(HttpMsg);