【问题标题】:How to track URL redirects using Delphi and Indy?如何使用 Delphi 和 Indy 跟踪 URL 重定向?
【发布时间】:2012-06-13 06:42:26
【问题描述】:

我收到了几封带有 url 链接的营销电子邮件,这些邮件从一个站点重定向到另一个站点。我想编写一个程序来使用 Delphi 和 Indy 跟踪每个 URL 重定向。我想遍历每个 URL,记录完整的 QueryString 以及在此过程中可能设置的任何 Cookie。

我如何使用 D2010 附带的 Indy 组件来做到这一点?

【问题讨论】:

  • 如果 TIdHTTP 没有为此公开适当的事件,您必须确保它不会自动处理重定向。意味着您必须自己响应“重定向”响应代码并为给定的 url 发出新的 get。抱歉,没有代码,我自己还没做过。
  • TIdHTTP 确实有一个 OnRedirect 事件,只要它检测到 HTTP 级别的重定向就会触发(重定向也可以使用客户端脚本完成,TIdHTTP 无法跟踪)。

标签: delphi url redirect query-string indy10


【解决方案1】:

首先你需要一个 HTTP 客户端,在 Indy 中是 TIdHTTP

现在你需要一个数据结构来保存你的结果:

  TRedirection = record
    queryString: String;
    cookies: TStrings;
  end;

  TRedirectionArray = array of TRedirection;

创建一个完成工作的类(需要一个类,因为事件函数定义为procedure of object):

  TRedirectionTester = class
    private
      FRedirData: TRedirectionArray;
      procedure redirectEvent(Sender: TObject; var dest: string;
        var NumRedirect: Integer; var Handled: boolean; var VMethod: TIdHTTPMethod);
      procedure newCookie(ASender: TObject; ACookie: TIdCookie; var VAccept: Boolean);
    public
      function traverseURL(url: String): TRedirectionArray;
      property RedirData: TRedirectionArray read FRedirData;
  end;

这提供了基本功能 - 您可以使用 URL 调用 traverseURL,它会返回一个包含查询字符串和 cookie 的 TRedirectionArray

然后实现OnRedirect事件:

procedure TRedirectionTester.redirectEvent(Sender: TObject; var dest: string;
  var NumRedirect: Integer; var Handled: boolean; var VMethod: TIdHTTPMethod);
var
  redirDataLength: Integer;
begin
  Handled := True;

  redirDataLength := Length(FRedirData);
  SetLength(FRedirData, redirDataLength + 1);

  FRedirData[redirDataLength].queryString := dest;
  FRedirData[redirDataLength].cookies := TStringList.Create;
end;

这将在数组中添加一个条目,并存储重定向的查询字符串。由于此重定向本身不包含 cookie(请求重定向页面时会设置 cookie),因此您还不能在此处添加任何 cookie。

这就是您需要OnNewCookie 处理程序的原因:

procedure TRedirectionTester.newCookie(ASender: TObject; ACookie: TIdCookie; var VAccept: Boolean);
var
  redirDataLength: Integer;
begin
  VAccept := True;

  redirDataLength := High(FRedirData);
  if (Assigned(FRedirData[redirDataLength].cookies)) then
    FRedirData[redirDataLength].cookies.Add(ACookie.CookieText);
end;

这只是将CookieText 添加到数据集中。该字段包含 cookie 的“摘要”——它是请求页面时发送的实际字符串数据。

最后,通过实现traverseURL 函数把它放在一起:

function TRedirectionTester.traverseURL(url: String): TRedirectionArray;
var
  traverser: TIdHTTP;
begin
  traverser := TIdHTTP.Create();
  traverser.HandleRedirects := True;
  traverser.OnRedirect := redirectEvent;
  traverser.CookieManager := TIdCookieManager.Create();
  traverser.CookieManager.OnNewCookie := newCookie;

  SetLength(FRedirData, 1);
  FRedirData[0].queryString := url;
  FRedirData[0].cookies := TStringList.Create;

  traverser.Get(url);

  Result := FRedirData;
end;

它做的不多:它创建所需的对象,并分配事件处理程序。然后它将第一个 url 添加为第一个重定向(即使它不是真正的重定向,我添加它是为了完整性)。 对Get 的调用然后发送请求。最终页面被webserver定位并返回后返回。

我用http://bit.ly/Lb2Vho测试了它。

但是,这仅处理由 HTTP 状态代码 301 或 302 引起的重定向。据我所知,它不处理通过 <meta> 标记或 javascript 完成的重定向。 要添加该功能,您必须检查对 Get 的调用结果,并对其进行解析以搜索此类重定向。

【讨论】:

  • HTTP 协议中没有任何内容可以阻止重定向响应在重定向时设置 cookie。任何 HTTP 响应都可以设置 cookie。
  • @Remy Lebeau:你当然是对的。这就是代码的作用:它记录 cookie,无论 HTTP 响应的类型如何。只是当您向域 x.com 发送请求时,它会将您重定向到域 y.com,然后将域 y.com 的 cookie 设置为对域 y.com 请求的响应(不在重定向中之前)。
  • @Chris - 我无法让它工作。我不能使用 TIdCookie(未声明的标识符),所以我改用 TIdCookieRFC2109 并且它编译得很好。现在,当我尝试调用 traverseURL 时,出现“AV at address”错误。
  • @CapeCodGunny:我使用的是 Delphi XE2,它也使用 Indy 10。这就是我假设 cookie 实现保持不变的原因。不幸的是,我的 Indy 版本只有 TIdCookie 但没有 TIdCookieRFC2109。但是,它们应该或多或少相同。你在哪个函数和哪一行得到 AV?
  • @chris:TRedirectionTester.traverseURL() 中存在内存泄漏。 TIdHTTPTIdCookieManager 对象没有被释放。
猜你喜欢
  • 2014-04-13
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
  • 2015-06-09
  • 2010-09-26
  • 1970-01-01
  • 2018-06-18
  • 2011-05-09
相关资源
最近更新 更多