« 大団円 | トップページ | はてな☆ログ:はてなスターを利用した足跡ログ取得サンプル »

2009/02/22

[JavaScript]GAE_xmlhttpRequest:クロスドメインのHTTP GET(Google App Engine経由)

JavaScriptでクロスドメインなHTTP GETを可能にするライブラリを試作してみました。
gae_xhrequest.js:JavaScriptでクロスドメインなHTTP GETを可能にするライブラリ
動作サンプル
といっても、Google App Engine(GAE)経由で、JSONPで取得しているだけですけどね(笑)。
■使用方法
<script type="text/javascript" src="http://furyu.tea-nifty.com/script/gae_xhrequest.js"></script>
のようにしてスクリプトを読込んだ後、
GAE_xmlhttpRequest({
    method              :   [HTTP Request種別(サポートしているのは'GET'のみ)]
,   url                 :   [取得するURL]
,   onload              :   [正常終了時(HTTP Status Code:200番台)のコールバック関数]
,   onerror             :   [異常終了時(HTTP Status Code:200番台以外)のコールバック関数](省略可)
,   onreadystatechange  :   [ReadyState変化時のコールバック関数](省略可)
,   headers             :   [HTTP Request時に指定するヘッダ要素(連想配列)](省略可)
,   timeout             :   [ローカルタイムアウト時間(秒)](省略時はタイムアウトなし)
,   ontimeout           :   [ローカルタイムアウト時のコールバック関数](省略可・timeout指定時は必須)
});
のような感じでGAE_xmlhttpRequest()をコールします。
コールバック関数は、
{
    status          :   [HTTP Status Code]
,   statusText      :   [HTTP Status 文字列]
,   responseHeaders :   [HTTP Response Headers(文字列)]
,   responseText    :   [応答内容(ページコンテンツ)]
,   readyState      :   [ReadyState(HTTP Request実行段階:1~4)]
,   rspheaders      :   [HTTP Response Headers(連想配列:rspHeaders['Content-Type']のように参照可能)]
}
のような連想配列が引数に指定されてコールされます。

【使用例】
GAE_xmlhttpRequest({
    method              :   'GET'
,   url                 :   'http://www.google.co.jp'
,   onload              :   function(xh){alert(xh.responseText)}
});
パラメータなんかは、基本的にGM_xmlhttpRequest()にあわせてあります(ただし、timeout, ontimeout, rspheadersはオリジナルです)。
……が、もちろんいろいろ制限があります。そもそも"GET"しか出来ないし(苦笑)。
■注意書き
  1. 例によって無保証です。ご使用は個人の責任にて。
  2. HTTP Requestは"GET"のみサポートです。
    当然ながら、"POST"のパラメータである'data'は未サポートです。
  3. headers(HTTP Request Headers)に指定出来る要素は、Google App Engineのセキュリティ上の制限を受けます。
    例えば、"Referer"とかは指定しても無駄です(GAE側で無視されます)。
  4. ReadyState実装はいい加減です。
    onreadystatechangeを指定している場合、GAE_xmlhttpRequest()コールのタイミングでreadyState=1及び2、GAEからの応答があったタイミングでreadyState=3及び4が指定されて連続してコールバックされます。
  5. timeout/ontimeoutを指定していた場合、timeoutで指定した秒数が経過すると、ローカル的に要求がキャンセルされます。タイムアウト後にGAEからの応答があっても、onload/onerror/onreadystatechangeはコールされません。
  6. GAEの制限上、urlで指定したサーバ側が数秒(約5秒?)経っても応答を返さない場合には、エラーとなってしまいます(onerrorを指定していた場合はコールされます)。
    これはtimeout(ローカルのみで使用)とは独立です。
  7. コールバック時、HTTP Response HeaderはresponseHeaders(文字列(String):GM_xmlhttpRequest互換)及びrspheaders(連想配列(Object):独自拡張)のふたとおりで返されます。形式が異なるだけで、中身は同じです。
    responseHeadersだけだと解析が面倒なので、rspheadersを追加しました。rspheaders['Content-Type']みたいにして内容を参照出来ます。
  8. GM_xmlhttpRequest()にある(隠しオプション?)overrideMimeTypeは未サポートです(指定しても無視されます)。
    一応、responseTextの文字コードについてはサーバ(GAE)側で自動認識・変換し、ユーザが意識せずとも済むようにしたつもりです。
  9. リダイレクトはサーバ(GAE)側で自動でおっかけています(urlfetch.fetch()のfollow_redirects=True)。
  10. statusはurlで指定したサーバが返す値が入りますが、statusTextの方はGAE(urlfetch.fetch)では取得できないため、ローカル(ライブラリ)側でstatusを元に作ってます(一部、サーバ(GAE)側から返すものもあります)。
  11. パラメータチェックやエラー処理はすごくいい加減です(ライブラリ・サーバ側とも)。ご了承願います(汗)。
  12. フリーソフト扱いです。転載・改修など、ご自由にどうぞ。
    なお、気づいた点などありましたら、お知らせいただけると幸いです。
■覚え書きなど
  1. GM_xmlhttpRequestの場合は取得したページがUTF-8以外だとresponseTextが文字化けすることがあるため、overrideMimeTypeで文字コードを明示的に指定したりする必要がありましたが、GAE_xmlhttpRequest()の場合、サーバ(GAE)側で文字コードを自動認識・変換し、JSON(P)は常にUTF-8で返すようにしています。
    その上で、ライブラリ内でJSONP呼び出し時にUTF-8を明示的に指定するようにしているため、文字コードはブラウザにより自動変換されるので、ユーザは特に意識せずにすむようになっているはずです。
    もっとも、うまく行かないケースもあると思いますが(苦笑)。
  2. Yahoo!PipesのFetch Pageモジュールを使っても同様のことは可能なので(URLを渡すとページの内容(htmlソース)をJSONPとかで取得できるAPIをYahoo! Pipesで作った(管理人日記) - むぅもぉ.jpとか)今更の感はありますが、
    • PipesのFetch Pageモジュールだと、ちょっと大きなページだと取得出来ない場合がある。
    • Pipesでは日本語ページが結構文字化けしやすい。
    • PipesではHTTPプロトコルの付加情報(ヘッダ・ステータスコードなど)が扱えないが、GAEではある程度扱える。
    といった点で、GAEの方が多少ましかな、と。

« 大団円 | トップページ | はてな☆ログ:はてなスターを利用した足跡ログ取得サンプル »

パソコン・インターネット」カテゴリの記事

おもいつき」カテゴリの記事

覚書」カテゴリの記事

コメント

w[callback]=undefined;は、delete w[callback];にしたほうがいいと思います。
w[callback]=undefined;だとcallback in wがtrueになってしまいます。

undefinedさん(違、コメント有り難うございます。

| w[callback]=undefined;だとcallback in wがtrueになってしまいます。

そうか、それはよろしくないですね……うーん。
実は、最初は delete w[callback] にしていたのですけれど、例によってIE某が例外的な動きになったため、やむなくこうしていたわけなのですが……。
#「このオブジェクトではサポートされていない操作です」とか言われてエラーとなってしまう……どうも、windowオブジェクト直下のものはdelete出来ない模様。

その後試してみて、window.cushion.callback のように一段かましてやれば、IE某でもcallbackをdelete出来るようなので、 とりあえずそのようにしてみました。

GAEについて、よく分かっていないため、当たり前の質問かもしれませんが、よろしくお願いします。
GAE_xmlhttpRequest を使って取得したページの内容は、実際のページの内容をリアルタイムに反映していないようですが、仕方がないのでしょうか?
具体的には、http://typhoon.yahoo.co.jp/weather/jp/earthquake/ です。地震が起こった直後に読み込むと、実際には更新されているのに、GAE_xmlhttpRequest で取得するデータは、古いままになっていることが多いです。

GAE_xmlhttpRequest()では、サーバ側の負荷軽減のために一定時間キャッシュするような作りとなっています。
※現状は60分。

どうしても、という場合、headersの連想配列に
'Cache-Control':'no-cache,max-age=0'
を追加してみてください。
※ただし、あまりに頻繁なアクセスがあるような場合は制限をかけるなどの対策を取る場合もあり得ます。悪しからず。

ありがとうございます。チンプンカンプンですが、勉強してみようと思います。

コメントを書く

(ウェブ上には掲載しません)

トラックバック

« 大団円 | トップページ | はてな☆ログ:はてなスターを利用した足跡ログ取得サンプル »

戻るリンク追加

カレンダー

2019年9月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          

ココログカレンダーPlus

検索


    • Web全体 サイト内
    • 蔵書のISBNを入力して下さい
    • はじめる前
      初級者向け
      上級者向け
      ブログ紹介
      結果を表示

最近のトラックバック

コメントリストツリー化

無料ブログはココログ