【问题标题】:Delphi indy get page contentDelphi indy 获取页面内容
【发布时间】:2017-02-20 22:53:35
【问题描述】:

我在网上看了很多例子,但我不明白为什么我的代码不起作用。

我有一个如下所示的网址:

http://www.domain.com/confirm.php?user=USERNAME&id=THEID

confirm.php 是一个页面,它对 MySQL 数据库进行一些检查,然后页面的唯一输出是 0 或 -1(真或假):

<?php

//long code...
if ( ... ) {
 echo "0"; // success!
 die();
} else {
 echo "-1"; // fail!
 die();
} 

?>

我的 Delphi FireMonkey 应用程序必须打开上面的 URL,传递用户名和 id,然后读取页面的结果。结果只有 -1 或 0。这是代码。

//I have created a subclass of TThread
procedure TRegister.Execute;
var
  conn: TIdHTTP;
  res: string;
begin

  inherited;

  Queue(nil,
    procedure
    begin
       ProgressLabel.Text := 'Connecting...';
    end
  );

  //get the result -1 or 0
  try

    conn := TIdHTTP.Create(nil);
    try
      res := conn.Get('http://www.domain.com/confirm.php?user='+FUsername+'&id='+FPId);
    finally
      conn.Free;
    end;

  except
    res := 'error!!';
  end;

  Queue(nil,
    procedure
    begin

      ProgressLabel.Text := res;    
    end
  );

end;

res 的值始终为error!!,绝不为-1 或0。我的代码哪里出错了?从on E: Exception do 捕获的错误是:

HTTP/1.1 406 不可接受

【问题讨论】:

  • 看来error!! 仅在引发异常时发生。您应该阅读异常并让我们知道这实际上引发的确切异常。否则,我们所能做的就是猜测,我们可以做出数百万种可能的猜测。
  • 所以您的 except 块应该更像 except on E: Exception do begin res := 'EXCEPTION: ' + E.Messages; end; end; 请执行此操作,然后编辑您的问题以提供正在引发的确切异常。
  • 另外,如果您在 ARC 下,则无需释放对象
  • @AlbertoMiola 我忘了!你是对的
  • @JerryDodge 所以我应该检查我的 http 标头?

标签: delphi indy


【解决方案1】:

我找到了使用System.Net.HttpClient 的解决方案。我可以简单地使用这个功能

function GetURL(const AURL: string): string;
var
  HttpClient: THttpClient;
  HttpResponse: IHttpResponse;
begin
  HttpClient := THTTPClient.Create;
  try
    HttpResponse := HttpClient.Get(AURL);
    Result := HttpResponse.ContentAsString();
  finally
    HttpClient.Free;
  end;
end;

这很有效,并按我的预期给了我 -1 和 0。为了获得一个工作代码的例子,我已经对此进行了测试:

procedure TForm1.Button1Click(Sender: TObject);

function GetURL(const AURL: string): string;
var
  HttpClient: THttpClient;
  HttpResponse: IHttpResponse;
begin
  HttpClient := THTTPClient.Create;
  try
    HttpResponse := HttpClient.Get(AURL);
    Result := HttpResponse.ContentAsString();
  finally
    HttpClient.Free;
  end;
end;

function GetURLAsString(const aURL: string): string;
var
  lHTTP: TIdHTTP;
begin
  lHTTP := TIdHTTP.Create;
  try
    Result := lHTTP.Get(aURL);
  finally
    lHTTP.Free;
  end;
end;

begin

 Memo1.Lines.Add(GetURL('http://www.domain.com/confirm.php?user=user&id=theid'));
 Memo1.Lines.Add(GetURLAsString('http://www.domain.com/confirm.php?user=user&id=theid'))

end;

end.

第一个函数完美运行,但 Indy 引发了异常HTTP/1.1 406 不可接受。似乎 Indy 无法自动处理页面的内容类型。在这里你可以看到 REST Debugger 日志:

【讨论】:

  • Indy 却没有工作,这很糟糕,因为它总是给我 HTTP/1.1 406 不可接受的。这个解决方案更好。
  • Indy 工作得很好。该错误意味着您根本没有正确配置它以使用您的 PHP 页面,反之亦然。
  • "Indy 好像不能自动处理页面的内容类型" - Indy 没有页面类型的问题。报告错误的是 PHP,因为它在处理 Indy 的请求时遇到问题。
  • 所以你是在告诉我我的 php 页面内容类型有问题?从我在你上面的评论中看到的,Indy 基本上接受了一切。当我在开头设置 header("Content-Type: text/plain") 时,它可以完美地与 System.Net 一起使用,但不能与 Indy 一起使用。
  • @RaffaeleRossi 你应该认真考虑一下 Remy 所说的话,他是 Indy 图书馆的作者之一。您的问题是 Indy 遵循 HTTP 规则 :-)
【解决方案2】:

HTTP 错误406 Not acceptable 通常意味着服务器无法响应客户端所需的内容类型。服务器和客户端都需要根据需要适当地使用 MIME 类型。在这种情况下,您的客户端的 Accept 标头应该提供所需的响应类型,并且您的服务器也应该使用相同的响应。在您的情况下,Content-Type 很可能是text/plain

长话短说,您的客户端期望服务器未在其响应中明确返回的 MIME 类型。问题可能在任何一方,也可能在双方都有。

  1. 您的客户的Accept 标头必须提供您期望和需要的 MIME 类型。特别是AcceptAccept-CharsetAccept-LanguageAccept-Encoding。默认情况下,在 Indy TIdHTTP 中,这些标头应该基本上接受任何内容,假设这些标头没有被覆盖。 Accept 标头默认设置为 text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q‌​=0.8*/* 为任何 MIME 类型打开了大门。
  2. 您的服务器响应的Content-Type 必须是所提供的 MIME 类型之一,并且响应的格式也是客户端所需的。您的 HTTP 服务器可能未在其响应中提供适当的 Content-Type。如果服务器响应 */* 过滤器中的任何内容(应该意味着一切),那么客户端将接受它(假设服务器以 text/plain 响应)。如果服务器响应的内容类型无效(例如 textplain),则可能会被拒绝。

【讨论】:

  • 因此,如果服务器具有标头(“Content-Type: text/plain”),则客户端也必须能够读取 text/plain。对吗?
  • @RaffaeleRossi 您客户的 Accept 标头也需要反映相同的内容。
  • 默认情况下,TIdHTTP.Request.Accept 设置为 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'。这对 HTML 有更高的偏好,但仍然告诉服务器任何事情都是可以接受的。确保 PHP 服务器发送回正确的 Content-Type。
  • @Remy 确实。这基本上就是我要说的,只是更一般地关于广泛范围内的 HTTP,而不仅仅是 Indy。很可能是的,服务器返回了错误的内容类型。
  • +1 idk 对此投了反对票。顺便说一句@RaffaeleRossi,您应该在 PHP 文件的开头设置标题,看起来您正在发送具有默认内容的“裸”文档。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-06
  • 2011-05-12
  • 1970-01-01
  • 2011-02-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多