Подтвердить что ты не робот

Java - HttpUrlConnection возвращает кешированный ответ каждый раз

Я пытаюсь собрать статистические данные из обмена валюты Roblox для анализа. Поэтому мне нужны обновленные данные вместо кэшированного результата. Тем не менее, кажется, что независимо от того, что я делаю, результат все равно кэшируется. Похоже, что самый интуитивный вариант setUseCaches() не имел никакого эффекта и вручную настраивал заголовок, поскольку Cache-Control: no-cache тоже не работает. Я проверил заголовок Cache с помощью Fiddler2 и увидел, что его значение было Cache-Control: max-age=0, но оно также не изменило поведение программы. Вот соответствующие фрагменты кода:

URL:

private final static String URL = "http://www.roblox.com/my/money.aspx#/#TradeCurrency_tab";

Запрос GET:

    URLConnection socket = new URL( URL ).openConnection( );
    socket.setUseCaches( false );
    socket.setDefaultUseCaches( false );
    HttpURLConnection conn = ( HttpURLConnection )socket;
    conn.setUseCaches( false );
    conn.setDefaultUseCaches( false );
    conn.setRequestProperty( "Pragma",  "no-cache" );
    conn.setRequestProperty( "Expires",  "0" );
    conn.setRequestProperty( "Cookie", ".ROBLOSECURITY=" + ROBLOSECURITY );
    conn.setRequestProperty( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" );
    conn.setRequestProperty( "Accept-Language", "en-US,en;q=0.8" );
    conn.setRequestProperty( "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36" );
    conn.setDoInput( true );
    conn.setRequestMethod( "GET" );
    conn.connect();

    Scanner data = new Scanner( conn.getInputStream() );
    data.useDelimiter( "\\A" );
    String result = data.next();

    data.close( );
    conn.disconnect();

Может быть или не важно отметить, что он возвращает уникальный результат каждый раз, когда я перезапускаю программу, но не во время выполнения программы.

Update:

Анализ Wireshark (я немного изменил свой код с момента последнего):

GET /my/money.aspx HTTP/1.1
Pragma: no-cache
Expires: 0
Cookie: .ROBLOSECURITY=_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|*sensitive*
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Cache-Control: no-cache
Host: www.roblox.com
Connection: keep-alive

HTTP/1.1 200 OK
Cache-Control: private, s-maxage=0
Content-Type: text/html; charset=utf-8
Set-Cookie: rbx-ip=; domain=roblox.com; path=/; HttpOnly
Set-Cookie: RBXSource=rbx_acquisition_time=1/4/2016 12:45:21 AM&rbx_acquisition_referrer=&rbx_medium=Direct&rbx_source=&rbx_campaign=&rbx_adgroup=&rbx_keyword=&rbx_matchtype=&rbx_send_info=0; domain=roblox.com; expires=Wed, 03-Feb-2016 06:45:21 GMT; path=/
Access-Control-Allow-Credentials: true
Set-Cookie: rbx-ip=; domain=roblox.com; path=/; HttpOnly
Set-Cookie: RBXSource=rbx_acquisition_time=1/4/2016 12:45:21 AM&rbx_acquisition_referrer=&rbx_medium=Direct&rbx_source=&rbx_campaign=&rbx_adgroup=&rbx_keyword=&rbx_matchtype=&rbx_send_info=1; domain=roblox.com; expires=Wed, 03-Feb-2016 06:45:21 GMT; path=/
Set-Cookie: RBXEventTrackerV2=CreateDate=1/4/2016 12:45:21 AM&rbxid=59210735&browserid=3940274345; domain=roblox.com; expires=Fri, 22-May-2043 05:45:21 GMT; path=/
Set-Cookie: GuestData=UserID=-856460986; domain=.roblox.com; expires=Fri, 22-May-2043 05:45:21 GMT; path=/
P3P: CP="CAO DSP COR CURa ADMa DEVa OUR IND PHY ONL UNI COM NAV INT DEM PRE"
Date: Mon, 04 Jan 2016 06:45:20 GMT
Content-Length: 153751
4b9b3361

Ответ 1

Если кеширование происходит на стороне сервера, добавьте кэш-память к URL-адресу.

HttpURLConnection conn = ( HttpURLConnection )new URL( URL + "?_=" + System.currentTimeMillis() ).openConnection( );

Ответ 2

Я замечаю, что вы не говорите местному HttpURLConnection обходить свои собственные кеши.

HttpURLConnection наследует метод setUseCaches(boolean) от URLConnection. Из Javadoc для setUseCaches(boolean)

Устанавливает значение поля useCaches этого URLConnection для указанного значения.

Некоторые протоколы кэшируют документы. Иногда важно иметь возможность "туннелировать" и игнорировать кеши (например, кнопку "перезагрузить" в браузере). Если флаг UseCaches в соединении является истинным, соединение разрешено использовать всевозможные кеши. Если false, кеши следует игнорировать. Значение по умолчанию - DefaultUseCaches, значение по умолчанию равно true.

Ответ 3

Увидеть, как вы пробовали большую часть настроек кеша. Возможно, это не ваш клиент, а их сервис, который вызывает это. Я могу видеть из вашей информации, что у вас есть "Keep Keep-Alive". Возможно, вы могли бы попытаться установить это в "Connection Close", так как вы говорите, что каждый раз, когда вы перезагружаете свою программу, вы получаете результат без кэширования.

Это может быть не идеальным в производственных условиях, но, возможно, это может дать вам некоторое представление о том, что происходит.

Ответ 4

Мне не хватает контекста (как данный фрагмент кода, который вызывается несколько раз), чтобы точно определить проблему, но это может быть связано с повторным использованием объекта socket вместо создания экземпляра нового для каждого запроса.

Когда соединение открыто, настройка useCache не имеет значения. Посмотрите на реализацию sun.net.www.protocol.http.HttpURLConnection#connect:

protected void plainConnect()  throws IOException {
  if (connected) {
        return;         
  }
  // try to see if request can be served from local cache
  if (cacheHandler != null && getUseCaches()) {
  // ..
}

Если соединение было открыто, оно будет немедленно возвращаться и повторно использовать существующий экземпляр InputStream.

Ответ 5

Вы пробовали следующие заголовки:

Cache-Control: no-cache
Pragma: no-cache
If-Modified-Since: Sat, 1 Jan 2000 00:00:00 GMT

Ответ 6

Я предлагаю вам выполнить следующую операцию над вашим URL перед открытием сокета URLConnection:

URLConnection socket = new URL( URL.replaceFirst("#", "?cacheFrom=" + System.currentTimeMillis()+"#") ).openConnection( );