Как закешировать с помощью nginx любой сайт и не нарушить его логику

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

Нельзя кешировать:

  1. POST запросы — отправка логинов и паролей, добавление комментариев и так далее.
  2. Страницы зарегистрированных пользователей
  3. Адрес «админки»

Запрет на кеширование можно осуществить по следующим признакам:

  1. Анализируя тип запроса, мы найдем все POST запросы
  2. Как правило даные для авторизированных пользователей сохраняются в cookie
  3. Админка обычно имеет фиксированный URL

Итак, самое главное — это найти нужную cookie. Для этого достаточно зайти на сайт с логином и паролем, после чего посмотреть в браузере все cookie, присланные серером. Как правило, для анонимных пользователей cookie не высылается или ее название отличается.

Перейдем к практике. Допустим, мы выяснили что у нашего сайта cookie имеет имя MYSITE_некое-значение, а URL админки —http://mysite.com/adminka/

Приступим к написанию конфига nginx:

В секцию http добавим указание, где храить файлы кеша:

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=proxy_cache1:40m max_size=100m inactive=1h;

В директории конфигов nginx создадим файл с именем backend, в котором опишем всю логику кеширования бакенда, а именно — возможность исключать запросы из кеширования, хранить нормальные ответы в течении часа и в случае проблем с бакенда:

 

proxy_pass http://backend;

proxy_redirect http://backend/ /;

proxy_set_header Host $host;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header X-Forwarded-Proto $scheme;

proxy_set_header X-Real-IP $remote_addr;

proxy_cache_key "$scheme://$host$request_uri";

proxy_cache_bypass $do_not_cache;

proxy_no_cache $do_not_cache;

proxy_ignore_headers Set-Cookie Cache-Control Expires;

proxy_cache_use_stale updating error timeout invalid_header http_500;

proxy_cache proxy_cache1;

proxy_cache_valid 200 1h;
И наконец, собственно конфиг nginx:
server {

                server_name mysite.com www.mysite.com;

                listen 80;

                location /adminka {

                    set $do_not_cache 1;

                    include backend;

                }

                location / {

                    if ($http_cookie ~* "MYSITE_" ) { set $do_not_cache 1; }

                    if ($request_method = POST) { set $do_not_cache 1; }

                    include backend;

                }

                error_page 404 = @fallback;

                location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf)$ {

                    root /images;

                }

                location @fallback {

                    if ($http_cookie ~* "MYSITE_" ) { set $do_not_cache 1; }

                    if ($request_method = POST) { set $do_not_cache 1; }

                    include backend;

                }

}
Обратите внимание — мы не кешируем статику, если ее можно напрямую отдавать с диска.