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

Как проверить, является ли заголовок запроса jQuery.ajax() "Состояние 304 не изменено"?

Как проверить, если jQuery.ajax() заголовок запроса Состояние "304 не изменено"?

jqXHR.status обычно возвращает 200, даже если запрашиваемый заголовок "304 Not Modified".

ifModified:true не помогает много, потому что он прерывает запрос данных XHR.

4b9b3361

Ответ 1

Без обработки заголовков кеша вручную это невозможно. Обычно 304 ответа не доступны через XHR API:

Для 304 Не измененных ответов, которые являются результатом условного запроса сгенерированного пользователем агента , пользовательский агент должен действовать так, как если бы сервер дал ответ 200 OK с соответствующим контентом.

jQuery обычно не знает, что был ответ 304, потому что браузер сообщает вежливой лжи JavaScript о том, что на самом деле происходит по сети.

Но есть хорошие новости (вид): вы можете получить Ajax для получения ответа 304, но только вручную настроив заголовки кэша HTTP If-Modified-Since или If-None-Match в запросе:

Пользовательский агент должен разрешить setRequestHeader() переопределять автоматическую проверку кеша, задавая заголовки запросов (например, If-None-Match, If-Modified-Since), и в этом случае должны быть переданы ответы 304 Not Modified.

Итак, вы можете использовать код, например:

var xhr = new XMLHttpRequest();
xhr.open("GET", "foo.html");
xhr.setRequestHeader("If-Modified-Since", "Fri, 15 Feb 2013 13:43:19 GMT");
xhr.send();

Одна из основных трудностей заключается в том, как вы знаете, какую дату последнего изменения или ETag отправить? В браузере есть информация о кеше, которую он использует для отправки запросов, но он не будет передавать эту информацию с помощью JavaScript. К счастью, jQuery отслеживает заголовки Last-Modified и ETag из ответов Ajax, поэтому вы можете использовать ifModified:true, чтобы jQuery установил эти значения заголовка при следующем отправке запроса для этого ресурса.

Две вещи, чтобы отметить об этом:

  • 304 ответа не содержат данных. Это по дизайну. Предполагается, что если вы решили использовать кеширование, вы должны иметь копию данных, уже находящихся в вашем кеше! Если получение данных с сервера не является проблемой (т.е. Потому что у вас еще нет данных), почему вы используете кеширование? Кэширование должно использоваться, когда у вас есть старые данные под рукой и нужны только новые данные; таким образом, получение данных с 304 не должно быть проблемой.

  • jQuery должен иметь дату последнего изменения или ETag (использовать с If-None-Match), сохраненную из предыдущего запроса. Процесс выполняется следующим образом:

    • Первый выбор: jQuery не имеет информации о кеше, поэтому он не отправляет If-Modified-Since или If-None-Match. Когда ответ вернется, сервер может объявить данные с последним изменением или ETag, которые хранятся в jQuery для дальнейшего использования.

    • Последующие выборки: jQuery имеет информацию о кеше из последней выборки и пересылает эти данные на сервер. Если ресурс не изменился, запрос Ajax получает ответ 304. Если ресурс изменился, запрос Ajax получает ответ 200, а также новую информацию о кеше для jQuery, которая будет использоваться для следующей выборки.

    • jQuery не сохраняет информацию кэша (например, в файлах cookie) между перезагрузкой страницы. Поэтому первая выборка ресурса после перезагрузки страницы никогда не будет 304, потому что jQuery не имеет информации о кеше для отправки (т.е. Мы reset обратно в случай "первой выборки" ). Нет никакой причины, по которой jQuery не может сохранять информацию о кеше, но в настоящее время это не так.

В итоге вы можете использовать заголовки кеша, чтобы получить ответ JavaScript 304, но вы не можете получить доступ к собственному ETag браузера или дате последнего изменения для определенного ресурса. Таким образом, сам браузер может знать кеширование информации о ресурсе, но ваш код JavaScript этого не делает. В этом случае браузер будет использовать свои заголовки кеша, чтобы получить реальный ответ 304, но перенаправить ответ 200 на ваш код JavaScript, поскольку JavaScript не отправил информацию о кеше.

Невозможно, чтобы JavaScript 304-запросы полностью совпадали с фактическими ответами сети 304, поскольку информация о кеше, известная вашему браузеру, и информация о кеше, известная вашим кодом JavaScript, могут отличаться непредсказуемыми способами. Однако получение 304 запросов в большинстве случаев является достаточным для большинства практических потребностей в разработке.

Пример

Вот пример сервера, написанный в Node.js(но он должен быть достаточно простым для переноса на другие langauges):

require("http").createServer(function (req, res) {
  console.log(req.headers["if-modified-since"]);

  // always send Last-Modifed header
  var lastModDate = "Fri, 13 Feb 2013 13:43:19 GMT";
  res.setHeader("Last-Modified", lastModDate);

  // if the request has a If-Modified-Since header,
  //   and it newer than the last modification,
  //   then send a 304 response; otherwise send 200
  if(req.headers["if-modified-since"] &&
     Date.parse(lastModDate) <= Date.parse(req.headers["if-modified-since"])) {
    console.log("304 -- browser has it cached");
    res.writeHead(304, {'Content-Type': 'text/plain'});
    res.end();
  } else {
    console.log("200 -- browser needs it fresh");
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('some content');
  }

}).listen(8080);

При запуске этого сервера вы можете загрузить страницу в своем браузере и выполнить два разных теста в консоли браузера:

var xhr = new XMLHttpRequest();
xhr.open("GET", "/");
xhr.send();
xhr.onload = function() { console.log(xhr.status); }

Этот script всегда будет видеть ответ 200, даже если браузер поставляет заголовок запроса If-Modified-Since и получает 304 (который будет иметь все запросы после первого, после того, как браузер увидит сервер Last-Modifed заголовок ответа).

В отличие от этого script всегда будет отображаться ответ 304:

var xhr = new XMLHttpRequest();
xhr.open("GET", "/");
xhr.setRequestHeader("If-Modified-Since", "Fri, 15 Feb 2013 13:43:19 GMT");
xhr.send();
xhr.onload = function() { console.log(xhr.status); }

script предоставляет свой собственный заголовок запроса If-Modified-Since (через два дня после последней версии сервера); он не полагается на то, что браузер предоставляет для If-Modified-Since, и поэтому разрешено (по спецификации XHR) видеть 304 ответа.

Наконец, этот script всегда будет видеть 200:

var xhr = new XMLHttpRequest();
xhr.open("GET", "/");
xhr.setRequestHeader("If-Modified-Since", "Fri, 12 Feb 2013 13:43:19 GMT");
xhr.send();
xhr.onload = function() { console.log(xhr.status); }

Это связано с тем, что script использует If-Modified-Since, который предшествует дате последнего изменения сервера, поэтому сервер всегда отправляет 200. Сервер не отправит 304, поскольку предполагает, что у клиента нет кэшированной копии самой последней версии (т.е. Клиент объявляет, что он видел изменения с 12 февраля, но 13 февраля было внесено изменение, клиент, видимо, не видел).

Ответ 2

Также заголовки будут кэшироваться, если ответ приходит из кеша. Я воспринял это как шанс. Мой сервер отправляет уникальный заголовок md5. Это не имеет такого же эффекта, как: query = time(). Теперь на стороне JS проверьте последний заголовок md5 с текущим. Если вы получаете тот же самый заголовок MD5, как и раньше, ответ приходит из кеша. Я забыл все о JQuery, но увидел, что можно устанавливать и читать заголовки.

<?php
$oldMD5=filter_input(INPUT_SERVER,'HTTP_CONTENT_MD5',int);
if(!empty($oldMD5)){
  header('Content-MD5: '.(1+(int)$oldMD5));
}
--------------------------------------------------------------
<script>
var oldMD5=0;
//your Ajax implementation 
Ajax.setRequestHeader('Content-MD5',''+oldMD5);
var newMD5=parseInt(Ajax.getResponseHeader('Content-MD5'),10);
if(newMD5 && oldMD5<newMD5,10){
  oldMD5=newMD5;
  //not cached
}else{
  //cached
}

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

Ответ 4

Возможно, попробуйте это?

$.ajax({
    url: 'your-url',
    dataType: 'script',
    complete: function(xhr) { 
        if (xhr.status == 304) return;
        // or better: if (xhr.status != 200) return;
        // your code goes here
    }
});

Ответ 5

откройте ваш инспектор браузеров, и он покажет вам информацию о запросе ajax, включая статус.

для хрома, щелкните правой кнопкой мыши и выберите элемент проверки, затем перейдите на вкладку "Сеть".

для firefox, просто используйте firebug и выполните те же действия.