Вопрос или проблема
Сервер upstream возвращает 404 с заголовком Cache-Control: no-cache
.
Из-за этого nginx не кэширует запрос. Как я могу заставить его кэшировать запрос?
Это кэширование необходимо только для ответов upstream с кодом состояния 404.
Он может сохранить оригинальный заголовок и передать его клиенту, но я не хочу, чтобы он отправлял ‘свежий’ запрос на страницу.
Я также не хочу полностью удалять заголовок, так как некоторые запросы будут иметь соответствующий заголовок ‘cache control’, установленный на истечение, например, через 24 часа. Поэтому я не могу использовать proxy_ignore_headers
.
Мне повезло, что я могу делать это на основе кода ответа (404) и, перехватывая ошибку:
#user www-data;
#worker_processes 4;
#pid /run/nginx.pid;
#
#events {
# worker_connections 768;
# # multi_accept on;
#}
user www-data;
worker_processes 4;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
#access_log /dev/null;
#error_log /dev/null;
sendfile off;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
proxy_cache_path /tmp/nginx levels=1:2 keys_zone=STATIC:10m inactive=24h max_size=1g;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 default_server ssl;
listen [::]:443 default_server ssl;
server_name localhost;
ssl on;
ssl_certificate /opt/bitnami/nginxssl/nginxssl.crt;
ssl_certificate_key /opt/bitnami/nginxssl/selfbuild.key;
recursive_error_pages on;
location / {
proxy_pass https://localhost:9443/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache STATIC;
# Позволить заголовку Set-Cookie проходить.
add_header X-Proxy-Cache $upstream_cache_status;
proxy_cache_valid 404 60m;
error_page 404 /404.html;
proxy_intercept_errors on;
}
location /404.html {
proxy_pass https://localhost:9443/404.html;
proxy_hide_header Set-Cookie;
proxy_hide_header Cache-Control;
proxy_hide_header Expires;
proxy_hide_header Pragma;
proxy_hide_header X-Accel-Expires;
proxy_ignore_headers "Set-Cookie" "Cache-Control" "Expires" "X-Accel-Expires";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache STATIC;
add_header X-Proxy-Cache $upstream_cache_status;
proxy_cache_valid 404 60m;
}
}
}
Ответ или решение
Как заставить кэшировать запросы с заголовком "Cache-Control: no-cache" в Nginx при использовании обратного прокси
Вопрос о кэшировании запросов, которые возвращают 404-ошибки и содержат заголовок Cache-Control: no-cache
, является довольно распространенной задачей в настройках Nginx. Давайте разберем подход к ее решению, принимая во внимание все ключевые моменты, указанные в вашем описании.
Понимание проблемы
Когда upstream-сервер возвращает ответ с 404 и заголовком Cache-Control: no-cache
, Nginx по умолчанию не будет кэшировать этот ответ. Но поскольку вы хотите кэшировать только 404-ответы, необходимо задать специфические правила для их обработки.
Создание правильной конфигурации
Для достижения необходимого результата нужно выполнить несколько шагов, как было указано в вашем фрагменте конфигурации. Мы будем использовать директиву proxy_cache
и специальное управление заголовками.
Пример конфигурации Nginx
http {
...
proxy_cache_path /tmp/nginx levels=1:2 keys_zone=STATIC:10m inactive=24h max_size=1g;
server {
...
location / {
proxy_pass https://localhost:9443/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Настройка кэширования
proxy_cache STATIC;
add_header X-Proxy-Cache $upstream_cache_status;
proxy_cache_valid 404 60m; # Кэшировать 404 ответы на 60 минут
proxy_intercept_errors on; # Перехватываем ошибки
error_page 404 /404.html; # Обработчик для 404 ошибки
}
location /404.html {
proxy_pass https://localhost:9443/404.html;
proxy_hide_header Set-Cookie; # Игнорируем заголовок Set-Cookie
proxy_hide_header Cache-Control; # Игнорируем заголовок Cache-Control
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Настройка кэширования
proxy_cache STATIC;
add_header X-Proxy-Cache $upstream_cache_status;
proxy_cache_valid 404 60m; # Кэшируем 404 на 60 минут
}
}
}
Объяснение ключевых директив
-
proxy_cache: Эта команда активирует кэширование для указанного location-блока, используя путь, заданный в
proxy_cache_path
. -
proxy_cache_valid 404 60m: Данная директива указывает, что 404-ответы должны кэшироваться в течение 60 минут.
-
error_page 404 /404.html: При обработке ошибок 404, управление передается на страницу /404.html, которая также будет кэшироваться.
-
proxy_hide_header: Используется для удаления ненужных заголовков, таких как
Set-Cookie
иCache-Control
, чтобы предотвратить их влияние на кэширование.
Заключение
Следуя приведенной выше конфигурации, вы сможете кэшировать 404-ошибки, даже когда upstream-сервер отправляет ответ с заголовком Cache-Control: no-cache
. Это позволит избежать лишних запросов к серверу и снизить нагрузку, сохранив при этом оригинальные заголовки для последующего использования.
Помните, что важно протестировать конфигурацию на предмет ее корректности и оптимальности в зависимости от ваших конкретных условий и требований. Также стоит регулярно проводить аудит кэшируемых ресурсов и контролировать их эффективность.