Как я могу заставить кэшировать запросы с заголовком “Cache-Control: no-cache” в nginx, когда он используется в качестве обратного прокси и отвечает с кодом 404?

Вопрос или проблема

Сервер 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 минут
        }
    }
}

Объяснение ключевых директив

  1. proxy_cache: Эта команда активирует кэширование для указанного location-блока, используя путь, заданный в proxy_cache_path.

  2. proxy_cache_valid 404 60m: Данная директива указывает, что 404-ответы должны кэшироваться в течение 60 минут.

  3. error_page 404 /404.html: При обработке ошибок 404, управление передается на страницу /404.html, которая также будет кэшироваться.

  4. proxy_hide_header: Используется для удаления ненужных заголовков, таких как Set-Cookie и Cache-Control, чтобы предотвратить их влияние на кэширование.

Заключение

Следуя приведенной выше конфигурации, вы сможете кэшировать 404-ошибки, даже когда upstream-сервер отправляет ответ с заголовком Cache-Control: no-cache. Это позволит избежать лишних запросов к серверу и снизить нагрузку, сохранив при этом оригинальные заголовки для последующего использования.

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

Оцените материал
Добавить комментарий

Капча загружается...