2012-07-10 14 views
6

El sitio http://openbook.etoro.com/#/main/ tiene una transmisión en vivo de lo que se genera mediante javascript a través de solicitudes XHR keep-alive y obteniendo respuestas del servidor como cadena comprimida gzip JSON.Perl - HTTP :: Captura de proxy Comunicación XHR/JSON

Quiero capturar la alimentación en un archivo.

La forma habitual (WWW :: Mech ..) es (probablemente) no viable porque la necesidad de reverese de la ingeniería de todos los JavaScript en la página y la simulación del navegador es una tarea realmente difícil, por lo que buscamos una solución alternativa.

Mi idea es usar una táctica del hombre en el medio, por lo que el broswser hará su trabajo y quiero capturar la comunicación a través de un proxy perl, dedicado solo para esta tarea.

Puedo capturar la comunicación inicial, pero no la alimentación en sí. El proxy funciona bien, porque en el navegador en el que se está ejecutando el feed, solo mis archivos no funcionan.

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 se configura utilizando el proxy anterior para todas las comunicaciones.

El feed se está ejecutando en el navegador, por lo que el proxy lo alimenta con datos. (Cuando detengo el proxy, el feed se detiene también). Al azar (no se puede calcular cuándo) i consiguiendo el error siguiente:

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

¿Alguien puede mostrar una forma, cómo construt la correcta HTTP :: filtro proxy para Volquete toda la comunicación entre el navegador y el servidor regardles de keep_alive XHR?

+0

Estás reinventando la rueda. Escriba ctrl + shift + i para ejecutar Firefox Firebug/Opera Dragonfly/Chromium Inspecter y busque en el panel de red el aspecto de los pares de solicitud/respuesta HTTP. Alternativamente, use Wireshark, complete una captura, filtre la expresión 'http' en el cuadro combinado cerca de la parte superior, seleccione el paquete que inicia una solicitud, menú Analizar → Seguir flujo TCP para ver la representación de texto de un par de solicitud/respuesta HTTP . – daxim

+1

Lo siento @daxim, pero esta no es una solución.Ofc, puedo usar Firebug o cualquier otro panel de control del navegador (y lo usé para analizar). Puedo usar tcpdump y/o tcpflow también. Quiero capturar exactamente el feed (para un trabajo posterior) en un servidor sin cabeza (sin X), sin navegador. Gracias por su respuesta, de todas formas, pero si quiero capturar paquetes simples, no pediré una solución perl. – kobame

+0

@daxim, entiendo su punto de vista, pero la pregunta es legítima y muestra un problema real. (e IMO, es mucho mejor que las preguntas normales de SO-perl, como cómo usar tr /// :) Probé el guión, y tampoco sé la respuesta, ¿me pueden ayudar? – jm666

Respuesta

5

Aquí es algo que creo que hace lo que está buscando:

#!/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; 

No creo que necesita un filtro de cabecera por separado porque se puede acceder a cualquiera de las cabeceras que desea buscar en el uso $message->headers en el filtro corporal

Notarás que empujé dos filtros en la tubería. El primero es del tipo HTTP::Proxy::BodyFilter::complete y su trabajo consiste en recopilar los fragmentos de respuesta y garantizar que el filtro real que sigue siempre reciba un mensaje completo en $dataref. Sin embargo, el fragmento foreach recibido y almacenado en el búfer, se llamará al siguiente filtro y se pasará un $dataref vacío. Mi filtro los ignora al regresar temprano.

También configuré la canalización del filtro para ignorar todo, excepto las solicitudes GET que dieron como resultado respuestas JSON, ya que éstas parecen ser las más interesantes.

Gracias por hacer esta pregunta: era un pequeño problema interesante y parecía que ya habías hecho la mayor parte del trabajo duro.

+0

¡Sí! Has resuelto ambos problemas, a) obteniendo application/json yb) la fragmentación también. Muchas muchas gracias. :) – kobame

2

Establezca mime parameter, el valor predeterminado es filtrar únicamente los tipos de texto.

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

Gracias, daxim, esta es la solución para la mayoría del problema;) – kobame

Cuestiones relacionadas