If-modified-since і - кешування - - сайт роману парпалака

За що я люблю PHP, так це за те, що геніальні речі на ньому пишуться в кілька рядків. У цій замітці я продовжу міркувати про правильне використання заголовків в PHP. Якщо вам не все одно, як індексується пошуковими системами ваш сайт, якщо ви хочете заощадити трафік, ви знайшли саме те, що потрібно.

Як відомо, кешування на стороні браузера скорочує навантаження на сервер. Але для часто оновлюваних сторінок у нього є істотний недолік: інформація в кеші може застаріти і не відповідати дійсній інформації.

Для кожного документа, що віддається сервером, бажано видавати заголовок Last-Modified (в тому числі для правильної індексації, наприклад, Яндексом):

Для часто оновлюваних сторінок (я не кажу «динамічних», так як сторінка може кожен раз збиратися інтерпретатором PHP, але фактично змінюватися вкрай рідко) можна заборонити кешування наступним набором заголовків:

В принципі, для задовільної роботи сайту цього достатньо. Однак замість повної заборони кешування краще застосувати більш гнучкий механізм з використанням заголовка If-Modified-Since. Він присутній в запиті браузера, якщо в його кеші є копія документа, і його значення - якась дата зміни цієї копії. PHP-скрипт може подивитися на цю дату і вирішити, чи варто віддавати браузеру свіжу сторінку, або повідомити, що сторінка не змінилася, надіславши відповідь 304 Not Modified. Разом з відправкою заголовка Last-Modified. код набуде вигляду:

Справа в тому, що останні версії Opera і Firefox справно копіюють вміст заголовка Last-Modified відповіді сервера в заголовок запиту If-Modified-Since (саме тому нам потрібно було встановити Last-Modified), і перевіркою на рівність цілком можна було б обійтися. Але, як завжди, не обійшлося без примх IE 6. Він до заголовку If-Modified-Since додає параметр length. в чому і полягає перша проблема. Її можна вирішити застосуванням функції strpos. якби не друга проблема - хитрості пошукових роботів. Всі вони (крім робота Рамблера, який діє за описаною вище схемою) в заголовку If-Modified-Since (якщо взагалі його використовують) передають й не значення з Last-Modified. а дату останнього скачування документа. У такій ситуації вже не можна обійтися без згаданого перекладу дат в unixstamp (що і робить функція date2unixstamp).

Якщо заборонити кешування сторінки функцією no_cache. то Опера і Firefox при зверненні до такої сторінці використовують механізм з заголовком If-Modified-Since. і це вірно. Тобто кешування все одно відбувається, але браузер запитує у сервера, чи змінилася сторінка насправді, чи ні. Однак IE заборона на кешування сприймає буквально. В ході експериментів стало ясно, що якщо з трьох заголовків no_cache прибрати друге, то IE версій 6 і 7 починає працювати так, як нам потрібно. Може виявитися корисним коректне використання заголовка Expires. У ньому можна встановити час, протягом якого буде використовуватися тільки локальна копія документа в кеші. Цей спосіб дозволяє впоратися з надмірно нав'язливим кешуванням в IE. Наприклад, щоб копія в кеші була дійсна протягом доби, потрібно використовувати такий оператор:

Отже, як же використовувати всі ці можливості протоколу HTTP? Обробка заголовка If-Modified-Since корисна в будь-якому випадку. Наприклад, Яндекс рекомендує її використовувати. Якщо ви економите трафік і якщо сторінки оновлюються рідко, то забороняти їх кешування не потрібно. Можна заборонити їх кешування, тоді замість нього станеться запит до сервера з If-Modified-Since і 304 відповіддю. Це трохи збільшить трафік, але дозволить отримувати більш правильну статистику відвідувань: користувач зайшов на сторінку, а ми йому говоримо, що сторінка не змінилася, але в статистиці його враховуємо. Якщо документи оновлюються часто, практично завжди варто забороняти їх кешування. Видача 304 відповіді в більшості випадків компенсує можливе підвищення трафіку.

Крім описаного методу для перевірки актуальності копії документа в кеші існує ще один, заснований не на дату зміни сторінки, а на унікальному хеш-коді вмісту сторінки. Загальна назва для обох методів - Conditional Get, ви можете ознайомитися з додатковою інформацією про них.

Подивіться в блозі

Дякую за статтю!
А як зробити, щоб в Опері картинка, що видається скриптом не перезапускається, можете допомогти?

Ось моя функція:

Взагалі ви займаєтеся збоченням, якщо ваша мета - замінити справжній URL картинки на якийсь інший. Ви ускладнюєте життя собі і сервера, на якому буде крутитися ваш скрипт.

Подібні дії можуть мати сенс, якщо ви кожен раз генерітся різні картинки. Але навіть і в цій ситуації краще зберегти картинку на диск, і прописувати в HTML посилання на неї (якщо картинка буде актуальна, скажімо, для 100 показів сторінок).

Спасибі за швидку відповідь :)
До речі, я теж вже вирішив зберігати на диск картинку, але у мене mod_rewrite написаний так:

RewriteEngine On
RewriteRule ^ ([^.] +) $ Index.php

для створення красивих url і я Парс їх в скрипті руками. А як написати, щоб за будь-яких url відкривався скрипт index.php як щас, але з виключенням, що якщо в першому рівні є show_image, то тоді, щоб в папку йшло, де картинки лежать.

У mod_rewrite докладно я не розбирався, тому підказати не зможу. Я б на вашому місці зробив перенаправлення через mod_rewrite на різні скрипти в залежності від шляху (хоч це і не найкраще рішення).

Нічого з лічильниками зробити не можна. Вибирайте, що вам важливіше: лічильник liveinternet.ru або економія трафіку як у відвідувачів сайту, так і у вас на хостингу.

Я хочу враховувати користувачів навіть якщо віддаю їм тільки заголовок, що сторінка не змінилася. Якби це був мій власний лічильник, то все ок, а якщо я користуюся Li.ru? Можна спробувати після видачі коду 304 звернутися до сервера liveinternet.ru і емулювати хіт користувача. Правда, не знаю, як все це буде працювати. Треба б якось таке зробити.

Це досить цікаво. А якщо ситуація така, що при зверненні до сторінки через Аякс віддаються параметри ПХП скрипту, він робить картінук і повертає у відповіді щось типу "

". У такій ситуації навіть якщо кеш відключений, картинка кешируєтся браузером і ніяк не хоче отновляться. Що робити тоді?

З вашого опису мені не зрозуміла суть проблеми. Опишіть докладніше, що ви хочете отримати, що ви робите і що в результаті виходить.

Якщо в Ajax серверний скрипт повертає HTML-код, в якому є тег img, і ви не хочете, щоб відповідна картинка кеш, можна до src додати несуттєвий параметр на кшталт src = "https://written.ru/articles/technologies/site_building/ qwe.jpg? 8472 ", що генерується випадково.

Якщо картинка генерується на льоту, і щоразу змінюється, то в скрипті, який її генерує, потрібно прописати заголовки, що забороняють кешування.

Про всяк випадок я тільки що перевірив, що при видачі відповіді 304 Opera, FF і IE завантажують лічильник.

Відкриваю сторінку, яка віддає спочатку заголовок: # 'Last-Modified. # 'І вміст, потім кожен раз: # 'HTTP / 1.1 304 Not Modified #'.

Тестую все в FireFox 3.0.6, так як можу подивитися і заголовки, і активність мережі в firebug. У ньому саме така поведінка.

Зараз у мене немає часу розбиратися з цим питанням. Може бути потім подивлюся.

Можливо, є інші рішення тієї задачі, яка перед Вами стоїть?

Рішення тільки одне: залишити як є, поклавшись на правильну роботу з кешем двох браузерів: IE і Chrome, а на FireFox, Opera і Safari забити.

Інше рішення - відмовитися від такого виду кешування, але тоді доведеться кожного разу віддавати клієнту сторінку. Або писати на сервері перевірку, якщо клієнт прийшов на попередню сторінку, то не віддавати йому заголовок: # 'HTTP / 1.1 304 Not Modified #', що само по собі неправильно.

Дякую за статтю, до речі! Буду заглядати, раптом знайдеться рішення :)

function date2unixstamp ($ s)
return strtotime (substr ($ s, 5));
>

Спасибо большое :) Дуже знадобився ваш код.

Я звичайно не дуже розбираюся в цьому всьому. Мене цікавить як зробити це на вордпресс. Як-небудь можна? Що таке кешування я слабо уявляю, мені потрібно, щоб при відвідуванні сайту роботами на запит if modified since wordpress видавав справжню дату зміни сторінки. Ну ще бажано, щоб при кожному запиті видавав команду last modified. Це можна на wp зробити?

Не знаю, як найкраще подружити Вордпресс і If-Modified-Since / If-None-Match. Подивіться, що про це пишуть інші люди, поекспериментуйте з плагінами.

Так то то ж і воно, що не знайшов я плагіна такого. Взагалі, чим більше юзаю движки, тим більше розумію, що пих треба вчити і писати щось своє.

Шкоди від заголовка «Pragma» не буде. Для «пуленепробіваемость» його можна залишити.

по мені так не дуже гарний і не дуже лаконічний код, для такого простого завдання

особливо зворушливо
die;

Але ж все вже є в php: