未分類

Google App Engineでクロスドメイン通信


前回「秋はまだですか」と書きましたが、その日のうちに気温下がったw これでちょっと過ごしやすくなったかも。…薄着で寝ててちょっと風邪引きそうになったのは内緒(・ω・)

本題。
クロスドメインでの非同期通信(XMLHttpRequest Level2)をGoogle App Engineで実装したのでメモ。はまったポイントもいくつか書いておきます。

特にハマったのは出力ヘッダ周り。

Access-Control-Allow-Origin
これはあちこちのサイトに書かれてますね。このヘッダを「*」で出力してあげると他ドメインからの通信を受け付けるようになります。・・・が、これだけじゃダメなんです。

Access-Control-Allow-Methods
こいつを指定してあげないとサーバーが受け付けてくれません。GETならGET、POSTならPOST・・・と指定してあげないといけません。これは複数を一括指定できます(例:「GET, POST」)。あとPOST通信の時は「OPTIONS」も追加してあげる必要があります。

FirefoxはPOSTする前にOPTIONSを投げるので、受信サーバー側でそれを受け取るようにしてあげることが必要です。POST時、Firebugで通信を覗くと「OPTIONS」が投げられているのが分かります(下図)。

これFirefoxだけなんかな?

Access-Control-Allow-Headers
上に書いた二種のヘッダ出力でいける・・・と思ったらIEが通らない。なんでじゃいと思って調べたら、この「Access-Control-Allow-Headers」に’*’を指定してあげないと動かなかった・・・。(本当はヘッダの中身をちゃんと調べて指定するべきなんだろうけど、めんどくさかったのでw)

そういえば自分も最初勘違いしてたんですが、これらのヘッダはデータ受け取り側のサーバー(GET/POST先のサーバ)が出力しないとダメですよ。発信側がjavascriptの”setRequestHeader”でこれらのヘッダをつけても無意味です。

そうそう、クロスドメインでの通信で忘れちゃならないのがCookie。クロスドメインでの通信にはCookieを付与できません。いや正確にいえば、「IE以外」は付与できます。 IE、ま た お 前 か orz
このため、セッション保持は別の手法を取る必要があります。

参考になるかわかりませんがApp Engine側のサンプルコードをおいておきます。
追記: コメントでいただいた指摘事項を反映させました

ご存じだとは思いますが念のための注意書き。
XHR lv2はIE8以上, Firefox, Chrome, Safariでのみ有効です。IE6, 7, Operaでは使えません。
あとIE8では独自オブジェクトXDomainRequestを使用する必要があります。他のブラウザは今までと同じXHRを使えばOKです。Microsoft、なぜ独自実装なんかしたんだオイ。めんどくさいったらありゃしないぞ。

…大体こんなもんだったと思いますが、他に何かあったかなぁ。思い出したら書きます。

クロスドメインに対応させた非同期通信だけを行うjsライブラリも書いたんだけど、需要あるかなぁ。あればいずれアップしますです(・ω・)b

Facebook / 広告
2010年10月18日 | Posted in 未分類5 Comments » 

関連記事

コメント5件

  • […] This post was mentioned on Twitter by Masashi Shinbara, webdesignStatio. webdesignStatio said: Google App Engineでクロスドメイン通信 | Azrael 前回「秋はまだですか」と書きましたが、その日のうちに気温下がったw […]

  • […] 参考記事 Google App Engineでクロスドメイン通信 ※GAEソースはPhyson […]

  • […] 参考記事:Google App Engineでクロスドメイン通信 […]

  • hirano satoshi より:

    こんにちは。

    def options(self):の
    self.response.headers[‘Access-Control-Allow-Headers’] = ‘*’

    だと、少なくともChromeとSafariではエラーになります。

    Access-Control-Allow-Headersは「Access-Control-Request-Headersを引き写し、さらにサーバーが受け入れられるHeaderを追加する」仕様なので、options()を以下のようにすると動きました。

    def options(self):
    self.response.headers[‘Access-Control-Allow-Origin’] = ‘*’
    self.response.headers[‘Access-Control-Allow-Headers’] = self.request.headers[‘Access-Control-Request-Headers’]
    self.response.headers[‘Access-Control-Allow-Methods’] = ‘GET, POST, OPTIONS’

    ちなみに、キーが存在しないかもしれないdictをひくときは、こうすると例外が出ません。キーがないとfooには第2引数が入ります。

    foo = mydict.get(‘key’, None)

    平野 聡

  • wg koro より:

    返事が遅くなり申し訳ございません。
    ご指摘ありがとうございます!エントリー内容にいただいた指摘内容を反映させました。

    Access-Control-Allow-Headersは「Access-Control-Request-Headersを引き写し、さらにサーバーが受け入れられるHeaderを追加する」仕様なので、

    おお、そういう仕様だったのですね・・・。勉強になりました。ありがとうございます。

  • コメントを残す

    メールアドレスが公開されることはありません。

    スパム対策のため、コメントする際は下記の計算式を埋めてください。 計算式の有効期限が切れました。計算式の隣にある再読み込みボタンを押してください。