2008-09-25 16 views
6

Tengo un sistema de cliente/servidor que realiza comunicación utilizando XML transferido utilizando solicitudes y respuestas HTTP con el cliente utilizando Perl's LWP y el servidor que ejecuta Perl's CGI.pm a través de Apache. Además, el flujo se cifra con SSL con certificados tanto para el servidor como para todos los clientes.Comprimir solicitud HTTP con LWP, Apache y mod_deflate

Este sistema funciona bien, excepto que periódicamente el cliente necesita enviar grandes cantidades de datos. Una solución obvia sería comprimir los datos del lado del cliente, enviarlos y descomprimirlos en el servidor. En lugar de implementarlo yo mismo, esperaba utilizar la descompresión de entrada mod_deflate de Apache como se describe en here.

La descripción advierte:

Si se evalúa el cuerpo de la petición a sí mismo, no confían en la cabecera Content-Length! El encabezado Content-Length refleja la longitud de los datos entrantes del cliente y no el número de bytes de la secuencia de datos descomprimida.

Así que si proporciono un valor de longitud del contenido que coincida con el tamaño de los datos comprimidos, los datos se truncarán. Esto se debe a que mod_deflate descomprime la secuencia, pero CGI.pm solo lee el límite de longitud del contenido.

Como alternativa, si trato de ser más listo y anular el encabezado Content-Length con el tamaño de datos descomprimido, LWP se queja y restablece el valor a la longitud comprimida, dejándome con el mismo problema.

Finalmente, intenté hackear la parte de LWP que hace la corrección. El código original es:

# Set (or override) Content-Length header 
    my $clen = $request_headers->header('Content-Length'); 
    if (defined($$content_ref) && length($$content_ref)) { 
     $has_content = length($$content_ref); 
     if (!defined($clen) || $clen ne $has_content) { 
      if (defined $clen) { 
       warn "Content-Length header value was wrong, fixed"; 
       hlist_remove(\@h, 'Content-Length'); 
      } 
      push(@h, 'Content-Length' => $has_content); 
     } 
    } 
    elsif ($clen) { 
     warn "Content-Length set when there is no content, fixed"; 
     hlist_remove(\@h, 'Content-Length'); 
    } 

Y me cambió la línea de empuje para:

push(@h, 'Content-Length' => $clen); 

Desafortunadamente esto causa algunos problemas en el contenido (trunca o no) ni siquiera llegar a mi script CGI.

¿Alguien ha hecho esto? Encontré this que comprime un archivo antes de cargarlo, pero no comprime una solicitud genérica.

Respuesta

-1

No estoy seguro de si te sigo con lo que quieres, pero tengo un módulo personalizado de obtención/publicación, que utilizo para hacer algunas cosas no estándar. El siguiente código leerá cualquier cosa enviada por correo postal o STDIN.

read(STDIN, $query_string, $ENV{'CONTENT_LENGTH'}); 

En lugar de utilizar el valor de uso de $ ENV utilizar sus años. Espero que esto ayude, y lo siento si no es así.

1

No creo que pueda cambiar la longitud del contenido así. Confundiría Apache, porque mod_deflate no sabría la cantidad de datos comprimidos para leer. ¿Qué tal si el cliente agrega un encabezado X-Uncompressed-Length y luego utiliza una versión modificada de CGI.pm que usa X-Uncompressed-Length (si está presente) en lugar de Content-Length? (En realidad, probablemente no necesite modificar CGI.pm. Simplemente configure $ENV{'CONTENT_LENGTH'} en el valor apropiado antes de inicializar el objeto CGI o llamar a cualquier función CGI.)

O use un módulo de nivel inferior que use el cubo brigada para contar la cantidad de datos para leer.

1

Aunque dijiste que no querías hacer la compresión tú mismo, hay muchos módulos perl que harán las dos cosas por ti, Compress::Zlib por ejemplo.

Tengo un truco (con una parte de .net de la compañía) donde me pasan XML como un parámetro separado publicado en, luego puedo manejarlo como si fuera una cadena en lugar de meramente con cosas como SOAP.

Cuestiones relacionadas