为什么这个Web服务器返回Indy的代码404,但每个浏览器返回代码200?

时间:2013-04-13 15:09:26

标签: delphi indy

我有一个网址在所有浏览器中运行良好(5台在2台计算机上测试),但是如果我尝试使用Indy Http客户端的Get()获取页面内容,则返回错误代码404,找不到页面。这是最新的Indy SVN版本(4985)。

为什么此Web服务器会返回Indy的代码404,但每个浏览器的代码为200?

我怀疑这可能是Indy中的一个错误,因为URL中的“#”字符(Indy在#之后切断了所有内容)。如果是这样,有没有办法解决这个问题。也许用转义代码替换#char?

这是我的示例代码。所需要的只是带有Indy组件的Delphi以及带有按钮和备忘录的表单。

procedure TForm1.Button1Click(Sender: TObject);
var HTTPCLIENT1: TIdHTTP;
begin
  try
   try
     HTTPCLIENT1 := TIdHTTP.Create(nil);
     Memo1.Clear;
     with HTTPCLIENT1 do
     begin
          HandleRedirects := True;
          Request.UserAgent   := 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31';
          Memo1.Text := Get('http://www.visionofhumanity.org/gpi-data/#/2011/scor/');
          Caption := ResponseText;
     end;
   except
     On e: Exception do
     begin
          Memo1.Lines.Add('Exception: '+e.Message);
     end;
   end;
  finally
     HTTPCLIENT1.Free;
  end;
end;

2 个答案:

答案 0 :(得分:3)

你的怀疑是正确的。您已在请求中包含地址的#部分。浏览器不会这样做,因为该部分是为页内导航保留的。服务器不知道这一点,因此它尝试获取与您提供的完整 URL相对应的资源,包括#以及之后的所有内容。没有任何匹配,因此它以状态404失败。

要么像浏览器那样做,要么在将请求发送到服务器之前从URL中删除该部分,要么将Indy更新为修订版4987,以便它自动发生。仅仅逃脱角色将继续产生404状态。

答案 1 :(得分:3)

#是网址中的保留字符。如果要在URL中使用保留字符,则需要对它们进行URL编码。 TIdHTTP不会为您做到这一点。它要求您传入已编码的网址,但您传入的是未编码的网址。由于#未编码,因此会将其视为锚点并被剥离,因此您实际上是在请求http://www.visionofhumanity.org/gpi-data/,而是请回复404。

#已被网址编码为%23,因此请使用:

Memo1.Text := Get('http://www.visionofhumanity.org/gpi-data/%23/2011/scor/');

或者这个:

Memo1.Text := Get(TIdURI.URLEncode('http://www.visionofhumanity.org/gpi-data/#/2011/scor/'));

<击>

更新:我追查了这个问题。这是另一个TIdURI解析错误,这次涉及在/字符后面加上#个字符。 TIdURI在检查/字符之前检查#个字符,因此该网址的锚点部分最终位于TIdURI.Path属性中(之前它已经结束了TIdURI.Params属性),从而提交给服务器。我已经检查了一个新的修复程序(SVN rev 4987)。