Я пытаюсь использовать Java HttpURLConnection для «условного получения», но я никогда не получаю код состояния 304 - PullRequest
5 голосов
/ 17 августа 2011

Вот мой код:

    final HttpURLConnection conn = (HttpURLConnection) sourceURL.openConnection();
    if (cachedPage != null) {
        if (cachedPage.eTag != null) {
            conn.setRequestProperty("If-None-Match", cachedPage.eTag);
        }
        conn.setIfModifiedSince(cachedPage.pageLastModified);
    }

    conn.connect();

    if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {

        newCachedPage.eTag = conn.getHeaderField("ETag");
        newCachedPage.pageLastModified = conn.getHeaderFieldDate("Last-Modified", 0);

    } else if (conn.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
        // Never reaches here
    }

Кажется, я никогда не получал код ответа HTTP_NOT_MODIFIED, даже несколько раз подряд нажимая на один и тот же сервер - там, где определенно нет изменений на странице.Кроме того, conn.getHeaderField ("ETag") всегда кажется пустым, а иногда conn.getHeaderFieldDate ("Last-Modified", 0) возвращает 0. Я пробовал это на различных веб-серверах.

Может кто-нибудь сказать мне, что я делаю не так?

Ответы [ 2 ]

17 голосов
/ 17 августа 2011

Вы все зависите от конфигурации сервера.

Если вы получаете заголовок ответа Expires, это просто означает, что вам не нужно ничего запрашивать до истечения указанного времени.Если вы получаете заголовок ответа Last-Modified, это означает, что вы должны иметь возможность использовать If-Modified-Since для его проверки.Если вы получаете заголовок ответа ETag, это означает, что вы должны иметь возможность использовать If-None-Match для его проверки.

Давайте возьмем http://cdn3.sstatic.net/stackoverflow/img/favicon.ico в качестве примера (изображение значка Stackoverflow):

URLConnection connection = new URL("http://cdn3.sstatic.net/stackoverflow/img/favicon.ico").openConnection();
System.out.println(connection.getHeaderFields());

Это дает:

{null = [HTTP/1.1 200 OK], ETag = ["9d9bd8b1165cb1: 0"], дата = [ср., 17 августа 2011 г. 17:57:07 GMT], длина контента = [1150], последняя модификация = [ср, 06 окт. 201002:53:46 GMT], Content-Type = [image / x-icon], Connection = [keep-alive], Accept-Ranges = [байты], Сервер = [nginx / 0.8.36], X-Cache =[HIT], Cache-Control = [max-age = 604800]}

Теперь выполните If-Modified-Since с тем же значением, что и Last-Modified:

URLConnection connection = new URL("http://cdn3.sstatic.net/stackoverflow/img/favicon.ico").openConnection();
connection.setRequestProperty("If-Modified-Since", "Wed, 06 Oct 2010 02:53:46 GMT");
System.out.println(connection.getHeaderFields());

Это дает ожидаемое значение 304:

{null = [HTTP / 1.1 304 Not Modified], ETag = ["9d9bd8b1165cb1: 0"],Дата = [ср, 17 авг. 2011 17:57:42 GMT], последняя модификация = [ср, 06 окт. 2010 02:53:46 GMT], соединение = [keep-alive], сервер = [nginx / 0.8.36], X-Cache = [HIT], Cache-Control = [max-age = 604800]}

Теперь выполните If-None-Match с тем же значением, что и ETag:

URLConnection connection = new URL("http://cdn3.sstatic.net/stackoverflow/img/favicon.ico").openConnection();
connection.setRequestProperty("If-None-Match", "9d9bd8b1165cb1:0");
System.out.println(connection.getHeaderFields());

Это дает неожиданно a 200:

{null = [HTTP / 1.1 200 OK], ETag = ["9d9bd8b1165cb1: 0"], дата = [ср, 17 августа 2011 18:01:42 GMT], длина содержимого = [1150], последняя модификация = [среда, 06 октября 2010 г. 02:53:46 GMT], Content-Type = [image / x-icon], Connection = [keep-alive], Accept-Ranges = [байты], сервер= [nginx / 0.8.36], X-Cache = [HIT], Cache-Control = [max-age = 604800]}

Еще более удивительно, когда оба заголовка установлены случайным образомзначение мусора как ETag, сервер по-прежнему выдает 304. Это признак того, что If-None-Match полностью игнорируется сервером, стоящим за http://cdn3.sstatic.net. Это может быть (прокси) проблема конфигурации или может быть сделано полностью осознанно(не по понятным причинам imho).

0 голосов
/ 17 марта 2012

Или короче:)

Просто попробуйте установить время ожидания соединения, отличное от 0 .

conn.setConnectionTimeout( 3000);

Сделайте это после .openConnection ()

final HttpURLConnection conn = (HttpURLConnection) sourceURL.openConnection();
conn.setConnectionTimeout( 3000);

Если не установлено, readTimeout кроме 0.

conn.setReadTimeout( 3000);
...