2008-09-25 5 views
6

У меня есть клиент-серверная система, которая выполняет обмен данными с использованием XML, переданного с использованием HTTP-запросов и ответов с клиентом с использованием Perry LWP и сервера, на котором запущен Perl CGI.pm через Apache. Кроме того, поток шифруется с использованием SSL с сертификатами как для сервера, так и для всех клиентов.Сжатие HTTP-запроса с LWP, Apache и mod_deflate

Эта система работает хорошо, за исключением того, что периодически клиент должен отправлять действительно большие объемы данных. Очевидным решением было бы сжать данные на стороне клиента, отправить их и распаковать на сервере. Вместо того, чтобы реализовать это сам, я надеялся использовать Apache mod_deflate «Input Decompression», как описано here.

Описание предупреждает:

Если вы оцениваете тело запроса самостоятельно, не доверять заголовок Content-Length! Заголовок Content-Length отражает длину входящих данных от клиента, а не количество байтов потока распакованных данных.

Поэтому, если я предоставляю значение Content-Length, соответствующее размеру сжатых данных, данные усекаются. Это связано с тем, что mod_deflate распаковывает поток, но CGI.pm только читает до предела Content-Length.

В противном случае, если я попытаюсь перехитрить его и переопределить заголовок Content-Length с декомпрессированным размером данных, LWP жалуется и сбрасывает значение до сжатой длины, оставляя меня с той же проблемой.

Наконец, я попытался взломать часть LWP, которая выполняет коррекцию. Оригинальный код:

# 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'); 
    } 

И я изменил нажимную строку:

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

К сожалению, это вызывает некоторые проблемы, когда содержание (усеченные или нет) даже не добраться до моего CGI скрипта.

Кто-нибудь сделал эту работу? Я нашел this, который выполняет сжатие в файле перед загрузкой, но не сжимает общий запрос.

ответ

-1

Я не уверен, следую ли вы за то, что вы хотите, но у меня есть пользовательский модуль get/post, который я использую для создания нестандартных материалов. Нижеприведенный код будет читать все, что отправлено через сообщение, или STDIN.

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

Вместо использования значения $ ENV используйте свои. Я надеюсь, что это поможет, и извините, если это не так.

1

Я не думаю, что вы можете изменить Content-Length как это. Это смущает Apache, потому что mod_deflate не знает, сколько сжатых данных нужно читать. Как насчет того, чтобы клиент добавлял заголовок X-Uncompressed-Length, а затем использовал модифицированную версию CGI.pm, которая использует X-Uncompressed-Length (если присутствует) вместо Content-Length? (На самом деле вам, вероятно, не нужно изменять CGI.pm. Просто установите $ENV{'CONTENT_LENGTH'} на соответствующее значение перед инициализацией объекта CGI или вызовом любых функций CGI.)

Или используйте модуль нижнего уровня, который использует ковш бригаду, чтобы рассказать, сколько данных читать.

1

Хотя вы сказали, что не хотите делать сжатие самостоятельно, есть много модулей perl, которые будут делать обе стороны для вас, например, Compress::Zlib.

У меня есть чит (с .net частью компании), где я получаю XML как отдельный параметр, размещенный в, а затем может обрабатывать его, как если бы это была строка, а не faffing about SOAP like stuff.

Смежные вопросы