LWPのPOSTでバイナリが壊れる
LWPを使って、multipart/form-dataでバイナリデータを含むリクエストをSSL経由でPOSTすると、そのバイナリデータの部分が壊れてしまいます。
これはバグなのでしょうか?いろいろ探してみても情報が見つかりません。Proxy周りに似たようなバグがあるなどという情報は見つけたのですが、どなたか何か御存じないでしょうか。
具体的には、たとえば簡単な例をあげます。
まずチェック用のCGIスクリプトを用意します。
---------------------------------------
#!/usr/bin/perl
use strict;
my $buffer;
binmode STDIN, ':raw';
read(STDIN, $buffer, $ENV{CONTENT_LENGTH});
open my $fh, '>:raw', './request_body.dat' or die($!);
print $fh $buffer;
close $fh;
print "Content-type: text/plain\n\nOK";
exit;
---------------------------------------
これをcheck.cgiというような名前で、非SSLとSSLの2つのサイトに設置しておきます。
「:raw」などほとんど意味がないかもしれませんが、ようは受け取ったリクエストボディをそのままファイルに保存するだけのものです。
次に以下のようなバイナリデータ(GIFファイル)をPOSTするスクリプトを作って実行します。
---------------------------------------
#!/usr/local/bin/perl
use strict;
use LWP::UserAgent;
use HTTP::Request::Common 'POST';
my $ua = LWP::UserAgent->new();
my $http_res = $ua->request(POST('https://host/check.cgi',
Content_Type => 'form-data',
Content => [
test_data => 'ABCDEFG',
bin_data => ['./test.gif'],
],
));
$http_res->is_success or die $http_res->message;
print "OK\n";
exit;
---------------------------------------
まったく同じであるはずの、非SSLとSSLの2つのrequest_body.datファイルをバイナリエディタで比較すると、bin_dataの部分が異なります。法則性もよく判らず、かなり大きく違うようです。
ダメモトでlibwww-perlの最新版5.822を、Crypt::SSLeayも0.57をインストールしてみましたが状況は変わらず。
リクエストヘッダは特に問題なく、ようするにリクエストボディにバイナリデータが含まれるとエンコードに失敗するのかなと推測しています。
バイナリではない部分や通常のPOSTは問題ないのでOpenSSLのバグとは考えられないと思います。
それに、バイナリをPOSTなんてレアケースとも思えないんですが、情報が見つからないのも不思議で…。
何か情報を、あるいは代替案をご存知でしたら、御教授お願いいたします。
この手のものはLWPに依存しすぎていたため、他のHTTPでPOSTするようなものをよく知らないもので…。
お礼
ありがとうございました。 LWP::UserAgentで解決しました