0

我有一个在所有浏览器中都可以正常工作的 URL(在 2 台计算机上测试了 5 个),但是如果我尝试使用 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;
4

2 回答 2

3

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

#被 url 编码为%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在检查/字符之前检查#字符,因此 URL 的锚部分最终在TIdURI.Path属性中(以前它在属性中结束TIdURI.Params)并因此提交给服务器。我已经签入了一个新的修复程序(SVN rev 4987)。

于 2013-04-13T16:27:17.733 回答
3

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

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

于 2013-04-13T15:18:32.677 回答