Hatena::ブログ(Diary)

_development, RSSフィード Twitter

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とか偽装してみる

とよいかもしれません。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証