2012年7月25日水曜日

クライアント/サーバ間通信でのトラブル

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
最近になってビリーズブートキャンプに入隊した、たなけんです。
本エントリでは、クライアント/サーバ間通信でのトラブルとその解決方法について記載します。

現象の整理

Webクライアントからサーバにアクセスした際、あるブラウザ(Safari)では期待通りの結果が表示されるが、他のブラウザ(Chrome、Firefox)では期待通りの結果が表示されませんでした。
表示されない原因として、サーバから返されるhttpレスポンスのボディ部に、ブラウザ毎で下記の違いがありました。

  • Safari: httpレスポンスのボディ部にサーバから返されたデータが設定されている
  • Chrome & Firefox: httpレスポンスのボディ部に何も設定されていない


クライアントを疑う

ClojurescriptでのWebクライアントの実装は初めてだったため、もしかしたら何かバグを踏んでいるのではないかと思い、極力シンプルな2つのテストを実施しました。

  • ブラウザから直接アクセス: すべてのブラウザで期待した結果が得られた(リクエストのボディ部に設定したJSON文字列が表示された)
  • jQueryを用いたAjaxクライアントの利用: Clojurescriptと同様、Safariと他のブラウザで異なる結果となった

クライアントコード

これらの結果から、問題はクライアントの実装ではないと判断しました。

サーバ側を変更してみる

Compojureとブラウザ側のXmlHttpRequestとの相性問題などの可能性を考え、2つの異なるhttpサーバを用いたコードを作成し、各Webブラウザより先述したクライアント(jQuery版)からアクセスしたところ、下記の様な結果となりました。

  • Bishop (clojure/ringベースの別のwebサーバ(Web Machineクローンで、Webサービス提供用に機能を特化している)): Clojurescriptと同様、Safariと他のブラウザで異なる結果となった
  • restify (node.js上で動作するWebサーバ用ライブラリ): すべてのブラウザで期待した結果が得られた

Compojure同様clojure/ringベースの別のwebサーバであるBishopを用いても問題は解決せず、node.jsベースのrestifyでは問題なく動作することが分かりました。

トラブルの原因と解決方法

ブラウザからローカルのファイルにアクセスする場合には、ブラウザの起動オプション等を変更する必要があるという様な話は以前より知っていましたが、今回の現象はローカルのWebサーバへのアクセスなので、ブラウザの起動オプションを変更しても問題は解決されませんでした。
通常の開発と今回のとの相違として、httpサーバにアクセスしてindex.htmlを取得し、それをブラウザから操作するのではなく、ローカルで作成したindex.htmlをブラウザから直接開いて操作しているという点に思い至りました。つまり、サーバとしては自分がホストしているドメインとは異なるドメインからアクセスを受けたと認識している訳です。
そこで、外部ドメインからのアクセスを許可するようサーバ側のコードを変更しました。具体的にはhttpヘッダに"Access-Control-Allow-Origin" "*"を追加するよう改修しました。
改修の結果ChromeおよびFirefoxでも期待通りの結果を得ることができました。
今後クライアントサイドMVCフレームワークの流行等で、サーバとクライアントを切り離して開発することも増えるかと思います。その際、同様の問題が発生した場合には、サーバ側でAccess-Control-Allow-Originが適切に設定されているかどうかを確認すると良いという貴重な教訓を得ることができました。


今回の作業は以上。最後までお読み頂きありがとうございました。
たなけん(作業時間120分(トラブルシュート含む))

0 件のコメント:

コメントを投稿