【问题标题】:Perl - HTTP::Proxy capture XHR/JSON communicationPerl - HTTP::Proxy 捕获 XHR/JSON 通信
【发布时间】:2012-07-10 15:29:01
【问题描述】:

网站http://openbook.etoro.com/#/main/ 有一个实时提要,该提要由 javascript 通过 XHR 保持活动请求生成,并从服务器作为 gzip 压缩 JSON 字符串获取答案。

我想将提要捕获到一个文件中。

通常的方式 (WWW::Mech..) (可能)不可行,因为需要对页面中的所有 Javascript 进行反向工程并模拟浏览器确实是一项艰巨的任务,因此,寻找替代解决方案。

我的想法是使用中间人策略,因此浏览器将完成他的工作,我想通过 perl 代理捕获通信 - 仅用于此任务。

我能够捕捉到最初的通信,但不能捕捉到提要本身。代理工作正常,因为在浏览器中,提要只运行我的文件管理器不起作用。

use HTTP::Proxy;
use HTTP::Proxy::HeaderFilter::simple;
use HTTP::Proxy::BodyFilter::simple;
use Data::Dumper;
use strict;
use warnings;

my $proxy = HTTP::Proxy->new(
     port => 3128, max_clients => 100, max_keep_alive_requests => 100
);

my $hfilter = HTTP::Proxy::HeaderFilter::simple->new(
    sub {
        my ( $self, $headers, $message ) = @_;
        print STDERR "headers", Dumper($headers);
    }
);

my $bfilter = HTTP::Proxy::BodyFilter::simple->new(
    filter => sub {
        my ( $self, $dataref, $message, $protocol, $buffer ) = @_;
        print STDERR "dataref", Dumper($dataref);
    }
);

$proxy->push_filter( response => $hfilter); #header dumper
$proxy->push_filter( response => $bfilter); #body dumper
$proxy->start;

使用上述代理配置 Firefox 进行所有通信。

提要在浏览器中运行,因此代理向它提供数据。 (当我停止代理时,提要也停止了)。随机(不知道什么时候)我收到以下错误:

[Tue Jul 10 17:13:58 2012] (42289) ERROR: Getting request failed: Client closed

谁能告诉我一个方法,如何为 Dumper 所有浏览器和服务器之间的通信构建正确的 HTTP::Proxy 过滤器,无论 keep_alive XHR 吗?

【问题讨论】:

  • 你在重新发明轮子。键入 ctrl+shift+i 以运行 Firefox Firebug/Opera Dragonfly/Chromium Inspecter,并在网络面板中查看 HTTP 请求/响应对的样子。或者,使用 Wireshark,完成捕获,在顶部附近的组合框中过滤表达式 http,选择启动请求的数据包,菜单分析 → 跟踪 TCP 流以查看 HTTP 请求/响应对的文本表示.
  • 对不起@daxim,但这不是解决方案。 Ofc,我可以使用 firebug 或任何其他浏览器控制面板(并将其用于分析)。我也可以使用 tcpdump 和/或 tcpflow。我想在无头服务器(无 X)、无浏览器上准确捕获提要(供以后工作)。无论如何,感谢您的回答 - 但如果我想捕获普通数据包,则不会要求 perl 解决方案。
  • @daxim,我理解你的观点,但这个问题是合法的并且显示出真正的问题。 (和 IMO,它比通常的 SO-perl 问题要好得多,比如如何使用 tr/// :) 我试过这个脚本,但我自己也不知道答案 - 你能帮忙吗?

标签: perl forex


【解决方案1】:

以下是我认为你所追求的东西:

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;

use HTTP::Proxy;
use HTTP::Proxy::BodyFilter::complete;
use HTTP::Proxy::BodyFilter::simple;
use JSON::XS     qw( decode_json );
use Data::Dumper qw( Dumper );

my $proxy = HTTP::Proxy->new(
    port                     => 3128,
    max_clients              => 100,
    max_keep_alive_requests  => 100,
);

my $filter = HTTP::Proxy::BodyFilter::simple->new(
    sub {
        my ( $self, $dataref, $message, $protocol, $buffer ) = @_;
        return unless $$dataref;
        my $content_type = $message->headers->content_type or return;
        say "\nContent-type: $content_type";
        my $data = decode_json( $$dataref );
        say Dumper( $data );
    }
);

$proxy->push_filter(
    method   => 'GET',
    mime     => 'application/json',
    response => HTTP::Proxy::BodyFilter::complete->new,
    response => $filter
);

$proxy->start;

我认为您不需要单独的标头过滤器,因为您可以在正文过滤器中使用 $message->headers 访问您想要查看的任何标头。

您会注意到,我将两个过滤器推入了管道。第一个是HTTP::Proxy::BodyFilter::complete 类型,它的工作是收集响应块并确保后面的真正过滤器总是在$dataref 中获得完整的消息。但是对于接收和缓冲的每个块,将调用以下过滤器并传递一个空的$dataref。我的过滤器通过提前返回来忽略这些。

我还设置了过滤器管道以忽略除导致 JSON 响应的 GET 请求之外的所有内容 - 因为这些似乎是最有趣的。

感谢您提出这个问题 - 这是一个有趣的小问题,您似乎已经完成了大部分艰苦的工作。

【讨论】:

  • 是的!您解决了这两个问题,a.) 获取 application/json 和 b.) 碎片。非常非常感谢你。 :)
【解决方案2】:

设置mime parameter,默认只过滤文本类型。

$proxy->push_filter(response => $hfilter, mime => 'application/json');
$proxy->push_filter(response => $bfilter, mime => 'application/json');

【讨论】:

  • 谢谢你,daxim,这是大部分问题的解决方案;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-12
  • 1970-01-01
  • 2012-07-31
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多