perl CGI.pm 渡される引数の取り扱い

perlでCGI.pmを使ってCGIを作る際の話。
・CGIに渡されたパラメータは、別のサーバに対してのコンテンツ取得に使用する
・渡されるパラメータが何がどれくらいあるのかが特定できない
・こちらの内部管理用で不要なパラメータとして特定の文字列があるが、それは引き渡さない

こんな条件がある時に、どーやって、パラメータを取得するか、というところ。

use CGI;
my $q = new CGI;
# 不要なパラメータを消去
$q->delete('sessionid');
# 残ったパラメータを表示
foreach my $name ($q->param) {
    # $nameが持っている値が複数の場合もあるため
    # @_=$q->param($name)に格納して
    # それをforeachする
    foreach my $value ($q->param($name)){
        print "$name=$value <br>\n";
    }
}

perl LWPを使ってcookie必須のページへのPOSTアクセス

うちで主に携帯向けとして提供しているゲームコンテンツのゲートウェイサービスは、内部でHTTP::Liteを使用して、オフィシャルのコンテンツを取りに行っている。

いままでは、それで問題なく利用できていたのだが、今回の動作状況見直しの際に、1点問題となる場面が見つかった。

それは、以下の様に同じ名前のパラメータで値が異なるものを送らなければならないことがある、ということ。

<input type="text" name="param" value="value1">
<input type="text" name="param" value="value2">

HTTP::Liteは、POSTアクセス時のコンテンツのペイロードに連想配列を使うため、同じ名前のものを複数送ることができない。

そんなわけで、LWPを使うように仕様変更を試みた。


HTTP::Liteを使用するもの

use HTTP::Lite;
$http = new HTTP::Lite;
$url="http://~";
$http->add_req_header("Cookie", "cookiename=$cookie");
%vars = ( "param" =>; "value1");
$http->prepare_post(\%vars);
$req = $http->request("$url")
    or $flagerr=1;
$contents=$http->body;

LWP使用に変更したもの

use LWP::UserAgent;
use HTTP::Headers;
use HTTP::Request;
$lwpua = LWP::UserAgent->new;
$url="http://~";
$lwpreq = HTTP::Request->new(POST => $url);
$lwpreq->content_type('application/x-www-form-urlencoded');
$lwpreq->header("Cookie"=>"cookiename=$cookie");
$lwpreq->content("param=value1&param=value2");
$lwpres= $lwpua->request($lwpreq);
$contents=$lwpres->as_string;

細かい点はいくつかあるものの、こんな感じで移行はできた。

失敗した点

最初「$lwpreq = HTTP::Request->new(POST => $url);」を「$lwpreq = HTTP::Request->new(POST => ‘$url’);」としていた。
この場合、「400 URL must be absolute」というエラーメッセージが出力されていた。
$urlにつけていたシングルクォーテーションを外したところ、正常動作した。

参考にしたLWP cookbookのサンプルは固定URLであるので、シングルクォーテーションで良いが、変数を使う場合にシングルクォーテーションを使うと駄目、という基本を忘れていたために食らいました。

もう1点、サーバに対して、Cookieの値を送る方法がよくわからなかった。
HTTP::Liteの時の例とかを考え、headerにCookieという名前で値を追加すればいい、と思い当たったので、それでやってみたところ、期待通りに動作した。