Истекает заголовок на основе динамического Content-Type в nginx

У меня есть веб-сайт PHP, где некоторый контент генерируется пользователем. Например, пользователи могут загружать фотографии, размер которых изменяется и может быть запрошен. Я хотел бы указать Expires заголовок (для кэширования) на основе типа MIME (Content-Type заголовок ответа) в моей конфигурации nginx.

Это моя текущая конфигурация (мой хост автоматически добавляет http{} а также server{}):

charset utf-8;

types {
    text/css            css;
    text/javascript     js;
}

gzip on;
gzip_types text/html text/css text/javascript application/json image/svg+xml;

location / {
    if (!-e $request_filename) {
        rewrite  .  /index.php last;
        break;
    }


    set $expire 0;

    if ($upstream_http_content_type = image/jpeg) { set $expire 1; }
    if ($upstream_http_content_type = image/png) { set $expire 1; }
    if ($upstream_http_content_type = image/gif) { set $expire 1; }
    if ($upstream_http_content_type = image/svg+xml) { set $expire 1; }
    if ($upstream_http_content_type = text/css) { set $expire 1; }
    if ($upstream_http_content_type = text/javascript) { set $expire 1; }

    if ($expire = 1) {
        expires max;
    }
}

Это работает для статических файлов (например, .png файлы - они получают право Expires заголовок), но это не влияет на динамически генерируемый контент из index.php (нет Expires заголовок вообще). Кто-то знает, что я делаю не так?

1 ответ

В вашем location Блок некуда, когда вы передаете запрос в php веб-приложение, поэтому я могу предположить, что вы делаете это где-то еще, например, в location блок, как этот:

location /index.php {
   # your code
}

С вашей конфигурацией, когда пользователь запрашивает статический файл, который существует тогда первым if директива не рассчитана и все идет хорошо. Проблемы начинаются, когда пользователь запрашивает динамические файлы, тогда nginx вводит ваш первый if блок:

if (!-e $request_filename) {
    rewrite  .  /index.php last;
    break;
} 

И вот что случилось? Ты используешь last флаг с rewrite директива, а что говорит по этому поводу документ nginx?

last - завершает обработку текущих директив перезаписи и перезапускает процесс (включая переписывание) с поиском совпадения по URI из всех доступных местоположений.

Согласно этой спецификации, когда файл динамический, вы сделали переписать index.php и исполнение уходит if блок и даже целый location блок и следующий if блок для проверки content-type даже не проверены. Я полагаю, найти location для URL /index.php и там вы не установите expires max,

Вы понимаете это расширение вашей проблемы?

Разрешение на это слишком переместить / скопировать ваш последовательный if блок для проверки content-type поместить место, где ваша конфигурация передает выполнение php веб-приложению (index.php)... или удалить last флаг от rewrite директива, если это не создает никаких других проблем.

Окей, так как я обещал немного исправить ваш файл conf: измените ваш location блок с этим двумя:

location /index.php {
   if ($upstream_http_content_type ~ "(image/jpeg)|(image/png)|(image/gif)|(image/svg+xml)|(text/css)|(text/javascript)") {
      expires max;
   }
   if ($sent_http_content_type ~ "(image/jpeg)|(image/png)|(image/gif)|(image/svg+xml)|(text/css)|(text/javascript)") {
      expires max;
   }
}

location / {
   if ($upstream_http_content_type ~ "(image/jpeg)|(image/png)|(image/gif)|(image/svg+xml)|(text/css)|(text/javascript)") {
      expires max;
   }
   if ($sent_http_content_type ~ "(image/jpeg)|(image/png)|(image/gif)|(image/svg+xml)|(text/css)|(text/javascript)") {
      expires max;
   }
   try_files $uri /index.php =404;
}

Первый location блок для вашего index.php и динамический ответ, в то время как второй для статических файлов. Во втором мы добавляем заголовок expires max в качестве верхнего заголовка и в качестве стандартного заголовка (просто чтобы быть уверенным). Я использую здесь один if блок для всех типов, которые вы определили в вашей конфигурации с помощью регулярного выражения. В конце мы используем try_files директива, которая означает, что если возможно получить статический файл на основе URL, он будет получен, и другим способом попробуйте url /index.php или просто вернитесь с http 404. Первый блок местоположения предназначен только для URL /index.php, Я нигде не нашел в твоем конфиге root директива, которая должна указывать на корневую папку вашего приложения. Попробуйте добавить это также ( root doc).

Я надеюсь, что это решит ваши проблемы.

Другие вопросы по тегам