知ったかFlash 第四回

どーも、お久しぶりです。kgmです。
久々の投稿です。

今回は、Flashのキャッシュ対策のTipsと、それを一歩踏み込んだものを紹介します。
一歩踏み込んだ・・・ってのをカンタンに説明しておくと、
キャッシュ対策の定番となっている手法を使うと、クエリのせいでログ解析が困難!
というのを解決するものです。

では早速。

まずは、rss的なXMLを読み込む場合を考えて見ましょう。

FlashのHelpにも書いていますが、基本的には下記のようなコードでXMLを取得することができます。

var rssXml:XML = new XML();
rssXml.ignoreWhite = true;
rssXml.load("http://hoge.com/rss.xml");

しかし、これだけでは問題があります。
ブラウザによって挙動は違いますが、物によってはキャッシュが強く、ブラウザの更新ボタンなどで更新しただけではXMLの内容がリフレッシュされないことがあります。
これでは非常にマズイです。最新の情報を表示することができません。

そこで、定番となるTipsが下記です。

var rssXml:XML = new XML();
rssXml.ignoreWhite = true;
rssXml.load("http://hoge.com/rss.xml?"+Math.floor(Math.random()*1000));

どこが変わったかというと、読み込む対象のXMLのURLが
“http://hoge.com/rss.xml?”+Math.floor(Math.random()*1000)となっています。

これは、“http://hoge.com/rss.xml”に、GET方式でクエリとして乱数(ランダムな数字)をくっつける事で、ブラウザに「前回とは違うファイル(リクエスト)である」と認識させることにより、しっかり新しいファイルを読み込ませるというものです。

Math.floor(Math.random()*1000)というのは、言葉で書くと
括弧の中の数字の小数点以下を切り捨て!(ランダムな0~1までの小数点以下ありの数字をつくります!それを1000倍!)ということです。

結果、0~1000までの数字(正確には0 <= n < 1000です)を通常のURLにクエリとして追加することとなります。 つまり、“http://hoge.com/rss.xml?123”というURLをリクエストすることになります。

ひとまずは、これにより当初の問題は解決します。
(もちろん、1/1000程度の確率でクエリもかぶりますが・・・一般的には無視することが多いみたいです。)

*追記 乱数ではなく、 “?”+new Date().getTime(); とすれば読み込み時刻をクエリとするので、上記問題は回避しやすくなります。ただ、ログのファイル名がほぼ無限になりますが・・・

・・・しかし!ここで新たな問題が発生します。
リクエストするURLが

“http://hoge.com/rss.xml?123”
“http://hoge.com/rss.xml?321”
“http://hoge.com/rss.xml?456”

といったように、リクエストするURLが毎回違うわけですからサーバーのログにも当然そのようにのこります。

見慣れたApacheのログであれば、
hoge.com – – [02/Dec/2008:22:46:49 +0900] “GET /rss.xml?523 HTTP/1.1” 200 1272
hoge.com – – [02/Dec/2008:22:46:51 +0900] “GET /rss.xml?778 HTTP/1.1” 200 1272
hoge.com – – [02/Dec/2008:22:46:53 +0900] “GET /rss.xml?515 HTTP/1.1” 200 1272といった感じで残ってしまいます。

これでは、ログ解析が大変煩雑になります。
rss.xmlについているクエリ自体はまったく意味を持ちません。

ですので解析時にクエリを無視しなければなりませんが、その場合は
rss.xmlのクエリだけ無視する
という設定にしなければ、意味を持つクエリまで無視されるような状況が想定されます。

これがカンタンにできるログ解析ソフトであれば問題ないでしょうが、その作業が必要なことを明示しておかなければログ解析する人がとっても困ります。

そこで、クエリを使わずにキャッシュが強いブラウザでも大丈夫な読み込み方法が下記です。
実装する際のコードなども含まれた状態にしています。

System.useCodepage = true;//XMLがShift_Jisの場合に必要
var rssXml:XML = new XML();//XMLを作成
rssXml.ignoreWhite = true;//お約束
var result_lv:LoadVars = new LoadVars();//sendAndLoadで読み込むので、結果格納用のLoadVars
result_lv.onLoad = function(success:Boolean) {//読み込み完了時動作
 if (success) {
  trace(unescape(this));//読み込み結果を出力ウインドウで確認。unescapeが重要です。
  rssXml.parseXML(unescape(this));//読み込んだ結果をXMLにパース。unescapeが重要です。
  txt.text = rssXml.firstChild.firstChild.firstChild.firstChild.nodeValue;//ノードの値を表示したり格納したり。
 } else {
  trace("Error connecting to server.");//読み込み失敗。
 }
}
 
var send_lv:LoadVars = new LoadVars();//読み込みLoadVars
send_lv.id = Math.floor(Math.random()*1000);//上記に、POST用の乱数くっつけます。
send_lv.sendAndLoad("http://hoge.com/rss.xml",result_lv,"POST");//POSTで読み込みます。

何をしているかと言うと・・・

  • 用意されたXMLのload関数を使わずに、外部プログラムと通信するLoadVarsのsendAndLoad関数を用いる
  • POSTメソッドでXMLファイルにアクセスする
  • さらにPOSTに乱数を仕込む事によって新しいリクエストであることを強調。
  • 上記で得られるのは、新しいXMLの内容であるが”テキスト”として読み込まれる
  • そこでXML.parseXML()関数を使い、テキストをXMLにパースする

という方法を取っています。
これにより、クエリを残さずに最新ファイルを表示することができます。

ただ・・・当然ですが
hoge.com – – [02/Dec/2008:22:46:33 +0900] “POST /rss.xml HTTP/1.1” 200 1272
というように、POSTでの要求というログが残ります。

また、サーバー環境やログ解析環境によっては期待した効果が得られないこともあるかもしれません。
結局、ログ解析者との意思疎通は必要になってくるかもしれません。

以上、意外とググっても見つからない問題だったので自分のやり方を書いてみました。
ほかにもやり方があるかも知れません。いい方法があれば、ぜひ教えてください!!

コメント / トラックバック 1 件

この記事へのコメント・トラックバックを追いかけることができます。(RSS 2.0

コメントをどうぞ

トラックバック URL

トラックバック

  1. […] 知ったかFlash 第四回-Re:Creator’s Kansai (リクリ) (tags: actionscript) […]