6

Perl の LWP を使用するクライアントと、Apache を介して Perl の CGI.pm を実行するサーバーとの間で、HTTP 要求と応答を使用して転送される XML を使用して通信を行うクライアント/サーバー システムがあります。さらに、ストリームは、サーバーとすべてのクライアントの両方の証明書で SSL を使用して暗号化されます。

このシステムは、クライアントが非常に大量のデータを定期的に送信する必要があることを除けば、うまく機能します。明らかな解決策は、クライアント側でデータを圧縮して送信し、サーバーで解凍することです。これを自分で実装するのではなく、ここで説明されているように、Apache の mod_deflate の「入力圧縮解除」を使用したいと考えていました。

説明では次のように警告されています。

リクエスト本文を自分で評価する場合は、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 スクリプトに到達しないという問題が発生します。

誰かがこれを機能させましたか?アップロードする前にファイルを圧縮するが、一般的なリクエストを圧縮しないこれを見つけました。

4

3 に答える 3

1

自分で圧縮を行いたくないとおっしゃっていましたが、たとえばCompress :: Zlibのように、両方の機能を実行するperlモジュールがたくさんあります。

私は(会社の.net部分で)チートを持っており、XMLを別のパラメーターとして投稿して渡され、SOAPのようなものに煩わされるのではなく、文字列であるかのように処理できます。

于 2008-09-26T13:21:07.107 に答える
1

そのようにContent-Lengthを変更することはできないと思います。mod_deflateは読み取る圧縮データの量を知らないため、Apacheを混乱させます。クライアントにX-Uncompressed-Lengthヘッダーを追加させてから、Content-Lengthの代わりにX-Uncompressed-Length(存在する場合)を使用するCGI.pmの変更バージョンを使用するのはどうですか?(実際には、おそらくCGI.pmを変更する必要はありません。CGI$ENV{'CONTENT_LENGTH'}オブジェクトを初期化する前、またはCGI関数を呼び出す前に、適切な値に設定するだけです。)

または、バケツリレーを使用して読み取るデータの量を指示する下位レベルのモジュールを使用します。

于 2008-09-26T07:06:41.353 に答える
-1

あなたが望むものをフォローしているかどうかはわかりませんが、標準ではないことを行うために使用するカスタムの get/post モジュールがあります。以下のコードは、郵便または STDIN 経由で送信されたものをすべて読み取ります。

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

$ENV の値を使用する代わりに、あなたの値を使用してください。これがお役に立てば幸いです。そうでない場合は申し訳ありません。

于 2008-09-26T01:35:21.617 に答える