3

我在使用 Delphi 和 Indy 9/10 从特定 Web 服务器接收 favicon.ico 时遇到问题。其他服务器工作正常。问题不在于此 Web 服务器,因为 wget 命令行实用程序可以正确获取文件。

这是 wget 的输出:

c:\a>wget http://perforce.eigenbase.org:8080/favicon.ico
SYSTEM_WGETRC = c:/progra~1/wget/etc/wgetrc
syswgetrc = c:/progra~1/wget/etc/wgetrc
--2013-01-27 00:12:39--  http://perforce.eigenbase.org:8080/favicon.ico
Resolving perforce.eigenbase.org... 72.14.190.177
Connecting to perforce.eigenbase.org|72.14.190.177|:8080... connected.
HTTP request sent, awaiting response... 200 No headers, assuming HTTP/0.9
Length: unspecified
Saving to: `favicon.ico'

    [ <=>                                   ] 2.862       --.-K/s   in 0s

2013-01-27 00:12:40 (143 MB/s) - `favicon.ico' saved [2862]

这是我的 Delphi Indy 9/10 示例代码。它生成一个“正常关闭连接”异常,结果是一个空字符串。

procedure TForm1.Button1Click(Sender: TObject);
var s: string;
begin
  s := '';
  try
    s := IdHTTP1.Get('http://perforce.eigenbase.org:8080/favicon.ico');
  except
     on E: Exception do
     begin
          {$IFDEF DEBUG}ShowMessage('get error:'+E.Message){$ENDIF};
     end;
  end;
  ShowMessage(IntToStr(Length(s)));
end;

如果我在不同的服务器上尝试相同的代码,例如:

s := IdHTTP1.Get('http://www.google.com/favicon.ico');

一切正常。

是否有解决方法可以使用 IdHTTP1.Get 从服务器获取http://perforce.eigenbase.org:8080/favicon.ico文件?

4

1 回答 1

7

失败的原因TIdHTTP是 wget 报告的关键信息:

没有标头,假设 HTTP/0.9

在 HTTP 0.9 响应中,根本不存在 HTTP 状态行和标头,只有原始文件数据本身,由断开连接终止。wget 支持,但TIdHTTP不支持(即使官方HTTP 1.0HTTP 1.1规范要求支持识别 HTTP 0.9 响应)。 TIdHTTP仅支持 HTTP 1.0 和 1.1 格式的消息,这需要使用 HTTP 状态行和标头。无论出于何种原因,此特定服务器选择为 Indy's 发送 HTTP 0.9 响应UserAgent,但选择为 Internet Explorer UserAgents 发送 HTTP 1.0 响应。奇怪的。

短期解决方案是按照@TLama 所说的去做。将TIdHTTP.Request.UserAgent属性设置为模仿 Internet Explorer 可以TIdHTTP.Get()正常工作:

procedure TForm1.Button1Click(Sender: TObject);
var
  icon: TMemoryStream;
begin
  icon := TMemoryStream.Create;
  try
    try
      IdHTTP1.Request.UserAgent := 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1';
      IdHTTP1.Get('http://perforce.eigenbase.org:8080/favicon.ico', icon);
    except
      on E: Exception do
      begin
        {$IFDEF DEBUG}ShowMessage('get error:'+E.Message){$ENDIF};
      end;
    end;
    ShowMessage(IntToStr(icon.Size));
  finally
    icon.Free;
  end;
end;

长期的解决方案是更新TIdHTTP以支持 HTTP 0.9 响应,即使它们现在很少遇到。为此,我在 Indy 的问题跟踪器中打开了票证。

于 2013-01-28T06:51:25.153 回答