Я хочу использовать nginx в качестве кеширующего обратного прокси. У меня также есть особое требование, которое, как я думал, можно выполнить с помощью nginx.
Я использую Amazon s3 в качестве исходного сервера и использую подписанные URL для защиты содержимого. Таким образом, каждый пользователь получает уникальный URL-адрес, срок действия которого истекает через определенное время. Даже несмотря на то, что у каждого пользователя есть уникальный URL, чтобы заставить nginx кэшировать контент независимо, я определил ключ кеша как состоящий только из имени файла запроса (см. Конфигурацию ниже).
Пока это работает очень хорошо. Проблема в том, что если URL-адрес запроса окажется недействительным из-за того, что подпись в строке запроса слишком старая или недействительная, сервер все равно доставит файл. Потому что он кешируется.
Я подтвердил, что первоначальный запрос должен содержать действительную подпись. Если сигнатура в запросе пользователя недействительна, nginx не может получить ее с сервера (конечно).
Теперь я хочу повторный поиск файла при каждом запросе. Этот повторный поиск должен происходить с URL-адресом, указанным пользователем. Если запрос выполнен успешно, кешированный файл должен быть доставлен.
Это именно то поведение, которое должно выполняться с помощью Cache-control: must-revalidate
Итак, я настроил этот заголовок на своем исходном сервере (Amazon s3).
Затем я понял, что nginx не ведет себя соответствующим образом.
Таким образом, файл доставляется напрямую из кеша без проверки на исходном сервере. Таким образом, плохая подпись не распознается, и пользователь может ее скачать.
Вопрос 1: есть ли способ заставить nginx соблюдать обязательную повторную валидацию заголовков в этом контексте?
Вот мой файл конфигурации
proxy_cache_path /home/sbgag/cache keys_zone=MYZONE:10m inactive=365d max_size=10g;
server {
listen 80;
server_name test.mydomain.com;
location / {
proxy_pass http://s3-eu-west-1.amazonaws.com;
proxy_set_header Host s3-eu-west-1.amazonaws.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_key "$request_filename";
more_set_headers "X-My-Proxy-Cache-Key $request_filename";
more_set_headers "X-My-Proxy-Cache-realpath_root $realpath_root";
more_set_headers "X-My-Proxy-Cache-uri $uri";
proxy_cache MYZONE;
proxy_cache_valid 200 365d;
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
more_set_headers "X-AppServer $upstream_addr"; # Backend Server / Port
more_set_headers "X-AppServer-Status $upstream_status"; # Backend HTTP Status
more_set_headers "X-Cache $upstream_cache_status"; # HIT / MISS / BYPASS / EXPIRED
}
}
Также я нашел это журнал изменений
*) Feature: the "proxy_cache_revalidate", "fastcgi_cache_revalidate", "scgi_cache_revalidate", and "uwsgi_cache_revalidate" directives.
Так что я подумал, что поиграю с этим. После доведения моего nginx до новейшей версии я установил время кеширования на 0 с. С 0s файл никогда не кешируется, поэтому я установил его на 1s.
Это производит почти поведение, которое я хочу. Это вызывает повторную проверку файла на сервере через 1 секунду. Затем он повторно подтверждается подписанным URL-адресом, предоставленным пользователем. Если он неверен, значит, он не работает. Кроме того, файл не удаляется, поскольку кажется, что nginx удаляет файлы не сразу, а только при заполнении места. Таким образом, даже если истекло время ожидания файла и даже если другой клиент предоставил недопустимый URL-адрес, следующий клиент с действительным URL-адресом может загрузить из кеша.
Однако в 1-секундном таймфрайме каждый может скачать, но это меня не беспокоит.
Хорошо, это почти то, что я хочу, но что мне не нравится, так это то, что это уродливая работа, основанная на поведении, которое более случайное, чем функциональное.
Вопрос 2: Нет лучшего способа?
Лучше всего я хотел бы передавать запросы в сценарий проверки, где я могу проверить запрос с помощью моего собственного сценария в фоновом режиме. И только если этот скрипт завершится успешно, загрузка будет разрешена. А затем использовать существующие проверенные алгоритмы кеширования nginx.
Маби, подойдет даже правило перезаписи. Перезапись в сценарий с картой перезаписи и вывод URL-адреса только в том случае, если проверка прошла успешно.
Любой вклад приветствуется!
Я думаю, что то, что вы ищете, на самом деле добавляет это:
proxy_cache_bypass $ http_cache_control;
Таким образом, отправка запроса с установленным заголовком Cache-Control: must-revalidate будет обходить кеш.