2011-04-01
GoogleはAndroidからの要求に冷たかった
Androidなどから、HTTP通信でAccept-Encoding=gzipするときの注意点
次のプログラムは、HttpURLConnectionでぐーぐるのトップページをリクエストするコードです。
Accept-Encodingでgzip圧縮を要求しており、ぐーぐるも当然gzip圧縮に対応しているので、レスポンスは圧縮されるはずです。
しかし、実際には圧縮されません。
以下はレスポンスが圧縮されないことを検証するコードです。
このJUnitテストを実行すると、 assertNull(contentEncoding) がパス、つまりContent-Encodingがnull、要するに圧縮されません。
public void testHttpResponseAreGzippedByAcceptEncodingFailDefaultAgent() throws IOException { final String urlString = "http://www.google.com/"; URL url = new URL(urlString); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); try { connection.setRequestProperty("Accept", "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"); connection.setRequestProperty("Accept-Encoding", "gzip,deflate,sdch"); connection.setRequestProperty("Accept-Charset", "UTF-8,*;q=0.5"); connection.setRequestProperty("Accept-Language", "ja,en-US;q=0.8,en;q=0.6"); InputStream is = connection.getInputStream(); is.close(); String contentEncoding = connection.getHeaderField("Content-Encoding"); // あれ? assertNull(contentEncoding); } finally { connection.disconnect(); } }
下は、User-Agentに"Mozilla/5.0"とか、よくあるマッチャーに反応するような値をセットしたケースです。
このケースは assertEquals("gzip", contentEncoding) でレスポンスが圧縮されることを検証しており、テストをパスします。
public void testHttpResponseAreGzippedByAcceptEncoding() throws IOException { final String urlString = "http://www.google.com/"; URL url = new URL(urlString); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); try { connection.setRequestProperty("Accept", "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"); connection.setRequestProperty("Accept-Encoding", "gzip,deflate,sdch"); connection.setRequestProperty("Accept-Charset", "UTF-8,*;q=0.5"); connection.setRequestProperty("Accept-Language", "ja,en-US;q=0.8,en;q=0.6"); // 妥当なUser-Agentを設定しないとGoogleがgzipで返してくれない。。。 connection.setRequestProperty("User-Agent", "Mozilla/5.0"); InputStream is = connection.getInputStream(); is.close(); String contentEncoding = connection.getHeaderField("Content-Encoding"); assertEquals("gzip", contentEncoding); } finally { connection.disconnect(); } }
両者の違いはUser-Agentの値です。
最初のケースはUser-Agentが未指定です。
User-Agentが未指定だと、URLConnectionの実装がつぎのような値を設定します。
(Androidじゃなくて、フツーのJavaだと、Java/1.4.0... とかになります。)
Dalvik/1.4.0 (Linux; U; Android 2.3.2; Nexus S Build/GRH78C)
そして、最初のテストの結果どおり、レスポンスは圧縮されません。
なのでぐーぐるのトップページ以外にも、同様の挙動をしめすページとか、WEB APIとかあるかもしれないので
- レスポンスが実際に圧縮されているか確認する
- 圧縮されていない場合はUser-Agentとか偽装してみる
とよいかもしれません。
トラックバック - http://d.hatena.ne.jp/esmasui/20110401/1301611814
リンク元
- 181 http://www.google.co.jp/url?sa=t&source=web&cd=1&ved=0CBkQFjAA&url=http://d.hatena.ne.jp/esmasui/20100410/1270920943&rct=j&q=android xml デコード&ei=TFSgTYD4HoKIvgO5stX3BA&usg=AFQjCNGof5jWPvwApGuyHqIS0WgbOpswew&
- 127 http://blogs.itmedia.co.jp/katabami/2010/07/androidbluetoot.html
- 118 http://www.google.co.jp/url?sa=t&source=web&cd=1&ved=0CBwQFjAA&url=http://d.hatena.ne.jp/esmasui/20091015/1255607482&rct=j&q=startDiscovery android&ei=oHegTabSJobevwPI6dmSBQ&usg=AFQjCNF5uXSOYTJq5a80Y0rc14RhqWQtVg
- 105 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4ADSA_ja___JP406&q=Android+Bluetooth+機器名 変更
- 96 http://www.google.co.jp/
- 77 http://d.hatena.ne.jp/kinneko/20110404/p13
- 69 http://www.google.co.jp/search?sourceid=chrome&ie=UTF-8&q=AndroidManifest 文字化け
- 64 http://code.google.com/p/android/issues/detail?id=719
- 63 http://www.google.co.jp/url?sa=t&source=web&cd=2&ved=0CCAQFjAB&url=http://d.hatena.ne.jp/esmasui/20091014/1255546770&rct=j&q=bluetooth 検出可能&ei=UeqwTYb4GYmcvgPD8amSBw&usg=AFQjCNEYNv9tTYjHaGDgWnGqz4wk53avmg&sig2
- 61 http://www.ecoop.net/memo/2010-10-21-1.html