Punta de Choros

27 декември 2009

На 2009г й оставаха 120ч съществуване. От календара падна поредния лист с дата 27 декември и към 10.30ч сутринта ме събуди звън от телефона.

Инсталация на Microsoft шрифтове в Ubuntu 16.04

14 януари 2017

нсталация на Microsoft шрифтове в Ubuntu се поражда от идеята браузърите в различните системи, да показват еднакво текстовото съдържанието на интернет страниците.

Ubuntu 16.04 инсталация на USB disk on Key

19 ноември 2016

Арсеналът ми от мобилни компютри съдържа Fujitsu Lifebook AH530. Това е бюджетна машина от 2011г на Intel Core i5-480M процесор и 4GB DDR3 RAM памет.

gparted

Paragon ExtFS for Windows

30 юли 2016

ExtFS for Windows е утилита на Paragon Software разработена през 2013г. Тя представлява решение, предоставящо пълен достъп на четене и на запис до раздели ...

msvcr100.dll is missing Windows 10

04 октомври 2016

Майк Патерсън от Plixer, компания по компютърната сигурност, публикува доклад , че Windows 10 изпраща данни в криптиран вид от вашата машина на всеки пет минути. Той е направил максимума, за да спре изтичането, но системата продължавала да изпраща информация.


Снимката долу показва съдържанието на каталог ajax, което е тестови сайт. Идеята е да се научим как да забраним на браузъра, да кешира нашите заявки и това е главния акцент. Съдържанието на кода не е обект на темата, а помощно средство за онагледяване.

test site

Главния проблем с когото всеки уеб-мастър се сблъсква е, че браузърите обожават да кешират отговорите на сървъра. Това е голям подводен камък, особено в AJAX и най-вече в IE-браузър. Всички браузъри кешират, дори прокси-сървърите, но при IE-браузър кеширането е съпоставимо с болест при заявка под метод GET.

метод GET и PHP


Хайде да спретнем малка демонстрация. Примитивен сървър, където PHP-сценарий връща тъпо времето. Досещате се, че това е файл gettime.php.
<?php
/*
 *  Сценарий, показващ текущото време
 */
//header("Content-type: text/plain; charset=utf-8");
//header("Current time: ". date("r"));
echo date('H:i:s');

По ред на браузърите правим следните действия.
  1. Заявка към файл gettime.php;
  2. Крачка назад в историята;
  3. Връщане обратно;
  4. Презареждане - F5;
Първи е Chromium браузър.

test site

Какво става на практика?
Заявка към файл gettime.php, печати в браузъра текущото време. Крачка назад в историята (оранжевата стрелка, сочеща наляво) и последвало връщане в текущия прозорец ни показва същото време. Няма изменение. Ако презаредим страницата - получаваме ново време, но ако пак прегледаме историята, то не се променя. И така с браузър Opera, Firefox и дори IE-9. Всички кешират!

Нека прихванем заглавките. А най-интересните са:
http://localhost/ajax/gettime.php

GET /ajax/gettime.php HTTP/1.1
Host: localhost
...

HTTP/1.1 200 OK
Date: Sat, 08 Jun 2013 17:50:33 GMT
Server: Apache/2.2.14 (Ubuntu)
X-Powered-By: PHP/5.4.15-1~lucid+1
...
Content-Type: text/html
Видно е, че метода е GET по протокол HTTP/1.1. Става ясно, че браузъра се обръща към PHP сценария, получава текущото време и до тук. То не се мени до нова заявка, а заигравката с историята е показателна, че отговора е кеширан.

метод GET и AJAX


Отлично. Нека усложним задачата и направим нещата под AJAX, за да проследим поведението на изброените браузъри.

xmlhttprequest.js е функцията, която връща обект XMLHttpRequest.
/*
** Функцията връща обект XMLHttpRequest
*/
function getXmlHttpRequest()
{
 if (window.XMLHttpRequest) 
 {
  try 
  {
   return new XMLHttpRequest();
  } 
  catch (e){}
 } 
 else if (window.ActiveXObject) 
 {
  try 
  {
   return new ActiveXObject('Msxml2.XMLHTTP');
  } catch (e){}
  try 
  {
   return new ActiveXObject('Microsoft.XMLHTTP');
  } 
  catch (e){}
 }
 return null;
Тази функция ще зацепим в индекс файла - index.html. Ето и него за финална сглобка на сайта.
<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>кеширане на заявка под метод GET</title>
 <script type="text/javascript" src="xmlhttprequest.js"></script>
 <script type="text/javascript">
  // заявка на данни
  function showServerTime()
  {
   var req = getXmlHttpRequest();
   req.onreadystatechange = function()
    {
     if (req.readyState != 4) return;
     var time = document.getElementById("time");
     time.firstChild.nodeValue = req.responseText;
    }
   req.open("GET", "gettime.php", true);
   req.send(null);
  }
  
  // автостарт
  window.onload = function()
   {
    setInterval("showServerTime()", 1000);
   }
 </script>
</head>
<body>
 <p>часовник <span id="time"> </span></p>
</body>
</html>
еквивалент на showServerTime()
function showServerTime(){
 var req = getXmlHttpRequest();

 req.open("GET", "gettime.php", true);
 req.onreadystatechange = function(){
  if (req.readyState === XMLHttpRequest.DONE && req.status === 200){
   var time = document.getElementById("time");
     
   time.innerHTML = req.responseText;
  }
 }
     
 req.send();
}
И разбира се правим заявка към индекса. На което Firefox 20.0, Chromium 25.0.1364.160, Opera 9.80 - linux версии честно показват часовника. Той тик-так-а. Отлично на функция setInterval и можем да отдъхнем, че браузърите са забравили да кешират. Тоест, отново чрез javascript се обръщаме към сървъра по метод GET, асинхронно. Получаваме времето и го пъхаме между таг-ове span на страницата.

browsers

Нека продължим. Откриваме Explorer9 9.0.5 под Windows 7 64-bit бла бла бла и хоп, не работи. Замръзване!

Explorer9

Към спънатия браузър се добави някаква стара Windows-версия на Opera. По-важното е, че може да ви се пръсне главата от мислене, защо в някои браузъри часовникът не работи. Скриптът е изряден и проблема остава в кеширането.

Смело може да се каже, че Windows-версия на Opera и Explorer9 честно са кеширали отговора и повече не се интересуват от измененията настъпили на сървъра. Тъпо се обръщат към кеша и четат значението съхранено там. Firefox в това отношение работи по-интелигентно и там кеширането става по желание на програмиста. Как ние можем да фиксираме това?

PHP забрана на кеширане


За съжаление много уеб-майстори не умеят това и тъпо преписват код, когото смело може да се нарече лайнокод. Същите дори не си правят труда, да видят ефективността на кода. Забранява ли въобще кеширането. Връх на невежеството е следния код:
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); //Дата в миналото
header("Last-Modified: ".gmdate("D, d M Y H:i:s")."GMT"); 
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 
header("Pragma: no-cache"); // HTTP/1.1 
Най-забавното е, че този код не работи. Добавяме го в gettime.php и рестартираме Explorer9. Никаква промяна с часовника, замръзва както преди.

Заглавка Expires по идея трябва да определи дата на актуалността на документа. Но защо всички тъпо преписват Mon, 26 Jul 1997 05:00:00 GMT? Наберете тази дата като ключова фраза в търсачката на Google и ще понесете огромна доза потрес, на колко сайта се намира тя.

Този код е наследство от хелпа на PHP версия 3 и неговият автор в ден преди приведената дата е търсил начин как да забрани кеширането от браузъра. Той е смятал, че като върне един ден назад в миналото това ще работи. Днес сме 2013г, а PHP е 5.4 версия. Така че това е тъпня. Смело може да прочетем глава 13 на RFC2616, за да разберем замисъла на кеширането и Expires. С думи прости отсичаме тази заглавка.

Заглавка Last-Modified показва датата на изменение на документа, считайки че браузърите могат да четат това. Вероятно през 1997г това е било нормално, но днес това е загубило своето значение и смело може да се заяви, че спъвате работата на паяците и после има да се чудите защо не ви обичат. Отсичаме я.

Заглавка Pragma: no-cache. Наполеон, когато отстъпвал от опожарена Москва, този метод вече бил остарял. Този код е ерата на HTTP/1.0 и на днешен ден на всички браузъри им е през фара. В киреча!

Остава една заглавка - Cache-Control. И тя действително контролира кеширането. За съжаление тя има около десетина възможни значения. Сега ще я приведем в боен вид и ще компенсираме Last-Modified.

Аплодисменти за gettime.php и елегантния му вид.
<?php
/*
 *  Сценарий, показващ текущото време
 */

header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); // HTTP/1.1 
echo date('H:i:s');

max-age и Expires е едно и също (поглед в снифера на заглавки). Най-главното е no-store и no-cache. no-store означава лични данни да не съхранява на локалния диск и той отсича кеширането в браузъра, а no-cache командва прокси-сървърите.

Рестартираме Explorer9 и о чудеса, часовникът тик-так-а!

Apache забрана на кеширането


Забраната за кеширане от браузъра може да се възложи на Apache. При всяка заявка той ще изпраща тази заглавки и по този начин няма да се чудите как да го постигате из документите на сайта ви. Досещате се че дойде ред на файл .htaccess от първата снимка горе.
# compiled modules enabled in apache on Debian
# user@machine:~$ /usr/sbin/apache2 -l
# <?php echo `/usr/sbin/apache2 -l`;
###############################################

# loaded modules enabled in apache on Debian
# user@machine:~$ ls /etc/apache2/mods-enabled/
###############################################

# list of disabled modules in apache on Debian
# ls /etc/apache2/mods-available/
###############################################

# enable mod_headers.c on Debian
# sudo a2enmod headers
# sudo /etc/init.d/apache2 reload
###############################################

# enable mod_expires.c on Debian
# sudo a2enmod expires
# sudo /etc/init.d/apache2 reload
###############################################

# header Cache-Control
###############################################
<ifModule mod_headers.c>
 Header set Cache-Control "no-store, no-cache"
</ifModule>

# header Expires
###############################################
<ifModule mod_expires.c>
 ExpiresActive On
 ExpiresDefault "now"
</ifModule>
Коректната работа на приведения .htaccess-файл за Debian базирани системи изисква включени модули mod_expires.c и mod_headers.c. Как се добавят става ясно от коментарите, които съм добавил в началото на файла.






до нови срещи   ^.^
08.06.2013 profruit 

0 Response to "Забрана кеширане от браузъра"

Публикуване на коментар

Този блог е реинкарнация на първите ми опити за споделяне в нета. На времето започнах с къси разкази на преживяното. После се обезсмисли и превърнах блога си в системно радио. Пиша единствено неща, които карат душата ми да живее: Ubuntu, WEB, Photoshop, Фотография, Споделено и т.н. Това е моето системно радио, разбирате ли? Моята вълна и вие сте на нея сега.

Архив на блога