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という名前で値を追加すればいい、と思い当たったので、それでやってみたところ、期待通りに動作した。

jQuery Mobileを使ってタブレット向けっぽいレイアウト その2

1つ前の記事では、横幅を狭めた時の動作があまりよろしくないので改善方法を調べた。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0rc1/jquery.mobile-1.0rc1.min.css" />
<link rel="stylesheet" href="http://jquerymobile.com/demos/1.0rc1/docs/_assets/css/jqm-docs.css" />
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="custom-scripting.js"></script>
<script src="http://code.jquery.com/mobile/1.0rc1/jquery.mobile-1.0rc1.min.js"></script>
<meta name="viewport" content="width=device-width; target-densitydpi=device-dpi" />
<title>テストページ</title>
</head>

<body>
<div data-role="page" id="jqm-home" class="type-home"> 
 <div data-role="content"> 
  <div class="content-secondary"> 
   <div class="ui-collapsible-content ui-collapsible-content-collapsed">

<p>横に長い時に、左側に表示されるサイドバーです。</p>
<p>class="ui-collapsible-content ui-collapsible-content-collapsed"でくくってある部分が表示されます。</p>
<p>横が短くなると消えます。</p>

   </div> <!-- end of ui-collapsible-content -->
   <div class="ui-collapsible-heading">

<p>サイドバーが表示されない時のメニューです。</p>
<p>class="ui-collapsible-heading"でくくってある部分が表示されます。</p>

   </div> <!-- end of ui-collapsible-heading -->
  </div><!-- end content-secondary -->    
  <div class="content-primary"> 

<p>メインコンテンツです。</p>

<p>ここにいろいろな内容をおいていきます。</p>


   </div><!-- end of content-primary -->
 </div><!-- end of content -->
</div><!-- end page -->
</body>
</html>

実行サンプル

ポイント
1. 以下のcssが必要
 http://jquerymobile.com/demos/1.0rc1/docs/_assets/css/jqm-docs.css

2. data-role=”content”の中で「class=”content-primary”」と「class=”content-secondary”」に分ける。

3. secondaryが左側のサイドバーになり、primaryがメインコンテンツとなる。

4. primary,secondaryはどっちが先でもおそらく大丈夫。

5. secondaryの中をさらに「class=”ui-collapsible-content ui-collapsible-content-collapsed”」と「class=”ui-collapsible-heading”」で分ける

とりあえず、これでレイアウト的には丁度いいものに、なった。

jQuery Mobileを使ってタブレット向けっぽいレイアウト

jQuery Mobileが1.0rc1になったというので、ドキュメントを読んでみた。

なんかタブレットっぽい感じの開き方になっている。
これを実現しようと思って調べてみた。

よく分からないなりに調べていくと、↓のURLを発見。
stackoverflow:Creating a sidebar in jQuery mobile

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0rc1/jquery.mobile-1.0rc1.min.css" />
<link rel="stylesheet" href="http://jquerymobile.com/demos/1.0rc1/docs/_assets/css/jqm-docs.css" />
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="custom-scripting.js"></script>
<script src="http://code.jquery.com/mobile/1.0rc1/jquery.mobile-1.0rc1.min.js"></script>
<meta name="viewport" content="width=device-width; target-densitydpi=device-dpi" />
<title>テストページ</title>
</head>
<body>
<div data-role="page" id="jqm-home" class="type-home">
    <div data-role="content">
        <div class="content-secondary">
            This would be the sidebar/split view on a tablet,
            would show up stacked on a mobile device
        </div><!-- end content-secondary -->

        <div class="content-primary">
            This is the main content.

            If Tablet device this would be to the right of the above content,
            if mobile this would be below the above content.

        </div><!-- end content-primary -->
    </div><!-- end content -->
</div><!-- end page -->

</body>
</html>

まだ実験途中ですが、ポイントっぽいもの
1. 以下のcssが必要
 http://jquerymobile.com/demos/1.0rc1/docs/_assets/css/jqm-docs.css

2. data-role=”content”の中で「class=”content-primary”」と「class=”content-secondary”」に分ける。

3. secondaryが左側のサイドバーになり、primaryがメインコンテンツとなる。

4. primary,secondaryはどっちが先でもおそらく大丈夫。

ぼちぼちと改造していきますよ

jQuery Mobile Loadingメッセージ変更

iUIを使ってcgiを作ってみたものの適切な公式ドキュメントが発見できず詳しい使い方がわからず、半ば挫折。
で、雑誌を立ち読んでいたらjQuery Mobileなるものが正式リリース間近だという記事を発見。
やってみたかったあたりがドキュメントとして紹介されていたので、こっちに乗り換えてみた。

で、出てきた疑問点と、その解決方法についてメモ書きしていってみる。

第1弾「Loading…」を変えたい

JavaScriptで設定する。
ドキュメントのConfiguring Defaultsに記載の設定を行う。

メインのhtml部分のjqeury.jsとjquery-mobile.jsの間に「custom-scripting.js」行を追加。

<script src="jquery.js"></script>
<script src="custom-scripting.js"></script>
<script src="jquery-mobile.js"></script>

custom-scripting.jsには以下を記述

$(document).bind("mobileinit", function(){
    //apply overrides here
    $.extend( $.mobile, {
         loadingMessage: "読み込み中..."
    });
});

ちなみに、最初、読み間違って「loadingMessage (string, default: “読み込み中…”);」と入れればいいのかと勘違いしました。