今日はデータベースとは関係のないネタです。
AirProxyというソフトウェアをご存知でしょうか。AirProxyはダイヤルアップ接続やAIR-EDGEなどのナローバンド環境において、ブラウズ対象のテキスト・画像を圧縮することでレスポンスを改善することができるHTTPプロキシソフトウェアです。
最近はイー・モバイルやUQ WiMAXなどモバイルブロードバンド環境が整備されてきたので、AirProxyを使っている人は減ってきたかもしれませんね。私はAIR-EDGEユーザなのですが、先日発売されたPocket WiFiの評判が良いので買うかどうか悩んでいるところです。
AirProxyはそうしたAIR-EDGEユーザの延命にも一役買っているわけですが、最新バージョンが2007年4月リリースということでかれこれ2年ほど更新されていません。そしてこの2年の間にうまく表示されないサイトが出てきていて、問題になっています。
というわけで、簡単に直してみました。
mixiアプリ対応
AirProxy経由でmixiアプリにアクセスすると、最初の画面がいつまで待っても出ません。これは以下のようなAjaxリクエストに失敗しているためです。
GET /social/data/people/@owner/@self?(略) HTTP/1.1 Keep-Alive: 300 Accept-Encoding: gzip,deflate Host: (略).app0.mixi-platform.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729) Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7 Referer: (略) X-Mixi-Platform-IO: 1 Content-Type: application/json Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: ja,en-us;q=0.7,en;q=0.3
HTTPリクエストヘッダにContent-Type: application/jsonが指定されているのですが、このHTTPリクエストにはボディが無いようです。ところがAirProxyはクライアントからHTTPリクエストボディが来るのをずっと待ってしまっています。
そのためContent-Typeがapplication/jsonのときは、HTTPリクエストボディを待たないように修正します。
*** org/http/server/HttpInputStream.java 2006-01-30 00:58:08.000000000 +0900 --- src/http/server/HttpInputStream.java 2009-11-29 19:33:04.000000000 +0900 *************** *** 209,214 **** --- 209,220 ---- this.isGzipEncoding = header.isGzipEncoding(); this.hasContent = (header.getContentType() != null); this.contentLength = header.getContentLength(); + + if (contentLength == -1 && header.getContentType() != null + && header.getContentType().indexOf("application/json") > -1) { + this.hasContent = false; + } + return header; }
これでAjaxリクエストが通るようになります。ただしこれはあくまで応急処置ですので、他のサイトで不具合が出る可能性がある点に注意してください。きちんと直すにはhttp.server.HttpInputStream#readHeader()を作り直す必要があると思います。
ニコニコ動画対応
AirProxy経由でニコニコ動画にアクセスすると、プレイヤーから「動画情報の読み込みに失敗しました」などのエラーが返されて動画を再生することができません。また、ローカルにキャッシュされているなどの要因により動画を再生できた場合でも、肝心のコメントが表示されません。
これは、動画プレイヤーがgzip圧縮されたコンテンツを読み込めないためです。AirProxyはHTTPレスポンスヘッダのContent-Typeを見て、圧縮可能な形式であれば圧縮を行うことによって通信量を削減するのですが、残念ながら動画プレイヤーはその圧縮されたデータを読み込むことができないようです。ちなみにHTTPリクエストヘッダにはAccept-Encoding: gzip,deflateがついているので、一方的にAirProxyの不具合というわけでもなさそうです。
うまくContent-Typeやその他のヘッダで振り分けることができればよいのですが、決まったパターンは見つかりませんでした。そのため、不本意ながら以下のようなURLフィルタリングで対処しました。
*** org/airproxy/extension/ExtensionManager.java 2006-01-22 15:07:56.000000000 +0900 --- src/airproxy/extension/ExtensionManager.java 2009-11-29 20:07:04.000000000 +0900 *************** *** 47,52 **** --- 47,57 ---- contentType = contentType.toLowerCase(); } + if ((url.indexOf("flapi.nicovideo.jp") > -1) + || (url.indexOf("msg.nicovideo.jp") > -1)) { + return null; + } + if(contentType.startsWith("image/")) { return imageExtensions; // new Extension[] { imageExtension }; }
これで動画やコメントが再生できるようになります。ただし、ニコニコ動画がバージョンアップして仕様変更するたびにメンテナンスが必要となります。
動画プレイヤーに返されるデータのContent-Typeは、今のところtext/plain、text/xml、application/xml、application/jsonの4種類となっています。いっそのことこれら4種類のコンテンツは圧縮をあきらめてしまった方がよいかもしれません。その場合、圧縮対象はtext/htmlのみとなります。