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とか偽装してみる
とよいかもしれません。