Изучаю браузерное кеширование, и кувыркаюсь неимоверно.
Из учебника код на PHP:
<?php
$etag = md5(__FILE__.filemtime(__FILE__));
header('Etag: ' . $etag);
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])
&& $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
header('HTTP/1.0 304 Not Modified');
exit;
}
sleep(5);
?>
<h1>Etag example</h1>
<?php
echo date("Y-m-d H:i:s").'<br />';
Пытаюсь повторить его на Python.
Для начала упростим его. Наша задача просто насадить ETag, и чтобы при повторном обращении к этой странице, на сервер летел заголовок If-None-Match.
Ниже вьюха на Django. В комментарии у нас - точка останова обозначена.
etag ="some_etag"
def home(request):
response = HttpResponse("Hello");
response['ETag'] = etag # Breakpoint
return response
Урлы сделал вот такие:
urlpatterns = [
url(r'^home', home),
url(r'^home/', home)
]
На всякий случай - чтобы переадресации какой не было со слешами.
Откроем Chrome и очистим кеш полностью (с самого начала).
chrome://cache/
Все чисто - ни одной записи.
Откроем инструменты разработчика.
Запустим отладочный сервер Django.
Идем на localhost:8000/home
Задушились на точке останова. И поехали дальше.
В кеше появилось http://localhost:8000/home
Request:
GET /home HTTP/1.1
Host: localhost:8000
Connection: keep-alive
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Response:
HTTP/1.0 200 OK
Date: Tue, 21 Nov 2017 14:46:48 GMT
Server: WSGIServer/0.2 CPython/3.5.2
X-Frame-Options: SAMEORIGIN
Vary: Cookie
Content-Length: 5
Content-Type: text/html; charset=utf-8
ETag: some_etag
Снова в Chrome ставим курсор на адресную строку браузера, нажимаем Enter.
Задушились на точке останова. Идем дальше.
Request:
GET /home HTTP/1.1
Host: localhost:8000
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Response:
HTTP/1.0 200 OK
Date: Tue, 21 Nov 2017 14:50:35 GMT
Server: WSGIServer/0.2 CPython/3.5.2
X-Frame-Options: SAMEORIGIN
Vary: Cookie
Content-Length: 5
Content-Type: text/html; charset=utf-8
ETag: some_etag
Теперь попробуем перейти на сторонний сайт. Скажем, lenta.ru. И вернемся кнопкой на наш сайт.
Request:
Request Headers
Provisional headers are shown
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Response:
HTTP/1.0 200 OK
Date: Tue, 21 Nov 2017 14:50:35 GMT
Server: WSGIServer/0.2 CPython/3.5.2
X-Frame-Options: SAMEORIGIN
Vary: Cookie
Content-Length: 5
Content-Type: text/html; charset=utf-8
ETag: some_etag
На точке останова не было остановки. Т.е. Chrome не отправлял запрос на сервер - взял из кеша. И показывает мне provisional.
Теперь проделаем то же самое в Firefox.
Чистка кеша.
Request:
Host: localhost:8000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:54.0) Gecko/20100101 Firefox/54.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Response:
Date: Tue, 21 Nov 2017 14:59:01 GMT
Server: WSGIServer/0.2 CPython/3.5.2
X-Frame-Options: SAMEORIGIN
Vary: Cookie
Content-Length: 5
Content-Type: text/html; charset=utf-8
Etag: some_etag
Опять ставим курсор в адресную строку, Enter.
Задушились на точке останова. Резьюм.
Request:
Host: localhost:8000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:54.0) Gecko/20100101 Firefox/54.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
If-None-Match: some_etag
Response:
Date: Tue, 21 Nov 2017 15:03:00 GMT
Server: WSGIServer/0.2 CPython/3.5.2
X-Frame-Options: SAMEORIGIN
Vary: Cookie
Content-Length: 5
Content-Type: text/html; charset=utf-8
Etag: some_etag
Ага - появился If-None-Match.
Перейдем на lenta.ru. Кнопкой обратно. На точке останова не остановался, т.е. на сервер не стучался. С запросом и ответом вообще какой-то ужас - до сих пор к lenta.ru как бы адресуется.
Request:
Host: icdn.lenta.ru
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:54.0) Gecko/20100101 Firefox/54.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://icdn.lenta.ru/assets/webpack/631d3915e50011177d6e.desktop.css
Cookie: lid=vAsAAKzrElrbK5o5AYxZAwB=; ruid=pA8AAK3rElqghZkAAXBMNgA=; _ga=GA1.2.113531064.1511189424; _io_un=; _ym_uid=15111894261069667896; last_visit=1511178631673::1511189431673; sspjs_1.0.186_FingerPrint=pA8AAGsis1fM0noHAfRZFgA%3D; sspjs_1.0.186_af_lpdid=%7B%22DATE%22%3A1511189438529%2C%22ID%22%3A%2221%3A494253725%22%7D; lids=48240CB010234C03
Connection: keep-alive
Response:
Server: nginx/1.13.4
Date: Tue, 21 Nov 2017 15:04:49 GMT
Content-Type: image/png
Content-Length: 6556
Last-Modified: Mon, 20 Nov 2017 14:04:39 GMT
Etag: "5a12e0f7-199c"
Expires: Wed, 21 Nov 2018 15:03:37 GMT
Cache-Control: max-age=31536000
Accept-Ranges: bytes
Ладно, бог с ним, с этим конкретным запросом.
А теперь посмотрим, как же у нас работает код на PHP. Для этого я его запустил с помощью веб-сервера Apache.
То же самое - чистим кеш хрома. Подчеркиваю, мы в Chrome.
Пишем в адресной строке: localhost
Закономерно ждем свои секунды, которые занимает sleep. Видим, что в кеше появился http://localhost/
Request:
GET / HTTP/1.1
Host: localhost
Connection: keep-alive
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Response:
HTTP/1.1 200 OK
Date: Tue, 21 Nov 2017 15:10:51 GMT
Server: Apache/2.4.18 (Ubuntu)
Etag: 78489ccce01dd927dcde3f39e94fa47c
Content-Length: 47
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
Встаем опять в адресную строку. Нажимаем Enter.
Request:
GET / HTTP/1.1
Host: localhost
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
If-None-Match: 78489ccce01dd927dcde3f39e94fa47c
Response:
HTTP/1.0 304 Not Modified
Date: Tue, 21 Nov 2017 15:14:30 GMT
Server: Apache/2.4.18 (Ubuntu)
Connection: close
Etag: 78489ccce01dd927dcde3f39e94fa47c
Я вообще ничего не понимаю. Вроде, тот же самый Etag.
Был бы признателен за помощь по двум вопросам:
1. Почему Chrome ни разу не послал на сервер If-None-Match в случае с питонячьей реализацией?
2. Почему код на PHP все же при том же самом Etag посылает на сервер If-None-Match?