使用LWP,Apache和mod_deflate压缩HTTP请求

时间:2008-09-25 21:56:29

标签: perl apache mod-deflate lwp

我有一个客户端/服务器系统,使用通过使用Perl的LWP的客户端使用HTTP请求和响应传输的XML以及通过Apache运行Perl的CGI.pm的服务器来执行通信。此外,流使用SSL加密,并为服务器和所有客户端提供证书。

该系统运行良好,但客户端需要定期发送大量数据。一个明显的解决方案是压缩客户端上的数据,将其发送出去,然后在服务器上解压缩。我没有自己实现,而是希望使用Apache的mod_deflate的“输入解压缩”,如here所述。

描述警告:

  

如果您自己评估请求正文,请不要相信Content-Length标题! Content-Length标头反映了来自客户端的传入数据的长度,而不是解压缩数据流的字节数。

因此,如果我提供与压缩数据大小匹配的Content-Length值,则会截断数据。这是因为mod_deflate会解压缩流,但CGI.pm只会读取内容长度限制。

或者,如果我试图超越它并使用解压缩的数据大小覆盖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在上传之前对文件进行压缩,但没有压缩通用请求。

3 个答案:

答案 0 :(得分:1)

我认为你不能像这样改变内容长度。这会让Apache感到困惑,因为mod_deflate不知道要读取多少压缩数据。如何让客户端添加X-Uncompressed-Length标头,然后使用使用X-Uncompressed-Length(如果存在)而不是Content-Length的CGI.pm的修改版本? (实际上,您可能不需要修改CGI.pm。在初始化CGI对象或调用任何CGI函数之前,只需将$ENV{'CONTENT_LENGTH'}设置为适当的值。)

或者,使用使用存储桶旅的较低级别模块来判断要读取的数据量。

答案 1 :(得分:1)

虽然你说自己不想自己进行压缩,但是有许多perl模块可以为你做双方,例如Compress::Zlib

我有一个作弊(公司的.net部分),我将XML作为一个单独的参数传递,然后可以处理它,就像它是一个字符串而不是像SOAP一样的东西。

答案 2 :(得分:-1)

我不确定我是否按照你想要的方式关注你,但我有一个自定义的get / post模块,我用来做一些非标准的东西。以下代码将读取通过post或STDIN发送的任何内容。

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

不使用$ ENV的值而是使用你的。我希望这会有所帮助,如果没有,我很抱歉。