根据 nginx 中的 mime 类型有条件地添加 expires 标头

根据 nginx 中的 mime 类型有条件地添加 expires 标头

在 ubuntu 12.10 上运行 nginx 1.4.1

需要有条件地并根据 http 响应的 mime 类型/内容类型发送 expires 标头。

在 location / { 中添加了这段简单的代码

if ($sent_http_content_type = "text/css") { 
expires 7d;
}

即使 $sent_http_content_type 包含“text/css”,也不会发送 expires 标头

如何修复这个问题?

检查文件扩展名是不够的,因为在我的应用程序中,js、css、图像都是从 php 动态生成的。因此,还需要检查 mime 并在此基础上添加标头。

答案1

从 nginx 1.7.9 开始:

map $sent_http_content_type $expires {
  default         off;
  application/pdf 42d;
  ~image/         max;
}

expires $expires;

注意:$sent_http_content_type 有效,但在服务器处理请求之前无法访问...

答案是指向application/pdf允许日期值的地图条目,甚至可以是application/pdf modified +42d例如

答案2

Nginx 中的指令if在重写阶段早期就被处理,因此$sent_http_content_type变量尚未初始化 - 参见这个 nginx 错误报告了解详情。

编辑通过比较用户名,那个错误报告实际上很可能就是你!(^_^)

同样,该expires指令似乎不像其他指令那样支持变量add_header。因此,由于您无法根据文件扩展名静态指定位置,我只能想到两种基本方法。

一种方法是使用Vadim 上面建议的map方法add_header来手动设置 HTTP 标头,而不是允许指令expires执行此操作。这种方法不太灵活,因为它不会设置标Expires头,但我希望现在的任何浏览器都可以通过Cache-Control设置来做正确的事情。下面是我简单测试过的一个示例:

map $sent_http_content_type $cacheable_types {
    "text/css"    "max-age=864000";
    "image/jpeg"  "max-age=864000";
    default       "";
}

# ...

server {
    # ...
    location / {
        # ...
        add_header "Cache-Control" $cacheable_types;
    }
}

价值864000是 10 天(以秒为单位)——您必须将其更改为您想要的任何值。这种方法的优点是您可以为每种文件类型指定不同的时间,甚至可以覆盖标Cache-Control头的其他方面——您可以讨论此标头这里以及来自 HTTP RFC 的官方部分这里如果您喜欢更正式一点的东西。

第二种方法是将导致可缓存内容的请求全部安排在特定路径下,您可以在location这样的指令中使用该路径:

location / {
    # ...
    location /static {
        expires 10d;
    }
}

这使得 nginx 配置更容易,因为您可以使用其内置expires指令,但这是否是一个选项很大程度上取决于您是否可以在代码上强制执行该 URL 模式。

答案3

$sent_http_content_type 无效。可以通过 $http_ 访问请求标头值姓名。此外,对于 Content-type 标头,nginx 已嵌入变量 $content_type。

如果你想根据多种类型检查 $content_type,最好使用 map:

   map $content_type $test_header {
        "text/css"  OK;
        "text/html" OK;
        ...
        default "";
   }

   server {
        location / {
             add_header "X-Test" $test_header;
        }
   }

如果 $test_header 计算结果为空字符串,则不会设置标题。

更多信息请参见: http://nginx.org/en/docs/http/ngx_http_core_module.html#variables http://nginx.org/en/docs/http/ngx_http_map_module.html http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header

答案4

如果必须使用 mime-type,请尝试:

if ($content_type ~= "text/css") { 
expires 7d;
}

但是,您可能需要考虑以下事情:

location ~ \.(css|js|htc)$ {
    add_header Pragma "public";
    add_header Cache-Control "max-age=31536000, public, must-revalidate, proxy-revalidate";
         log_not_found off;
         access_log off;

}
location ~ \.(html|htm|rtf|rtx|svg|svgz|txt|xsd|xsl|xml)$ {
    add_header Pragma "public";
    add_header Cache-Control "max-age=3600, public, must-revalidate, proxy-revalidate";
         log_not_found off;
        access_log off;

}
location ~ \.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mp
e|mpp|otf|odb|odc|odf|odg|odp|ods|odt|ogg|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|tif|tiff|ttf|ttc|wav|wma|wri|xla|xls|xlsx|xlt|xlw|zip)$
 {
    add_header Pragma "public";
    add_header Cache-Control "max-age=31536000, public, must-revalidate, proxy-revalidate";
         log_not_found off;
         access_log off;

}

我们在一个非常繁忙的站点上使用它,效果非常好。

相关内容