根据nginx中的MIMEtypes有条件添加expires标头

在Ubuntu 12.10上运行nginx 1.4.1

需要有条件地发送过期标题,并基于http响应的MIMEtypes/内容types。

在位置内添加了这段简单的代码/ {

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

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

如何解决这个问题?

检查文件扩展名是不够的,因为在我的应用程序js,css中,图像是从PHPdynamic生成的。 所以需要检查MIME并添加标题。

Nginx中的if指令在重写阶段就被处理了,因此$sent_http_content_typevariables还没有被初始化,详情参见这个nginx错误报告 。

编辑比较用户名,这个错误报告可能是你,其实! (^_^)

同样, expires指令似乎也不支持add_header那样的variables。 因此,由于您无法基于文件扩展名静态指定位置,因此我只能想到两种基本方法。

一种方法是使用上面提到的Vadim提供的mapadd_header方法来手动设置HTTP头,而不是允许expires指令去做。 这样做不太灵活,因为它不会设置Expires头文件,但是我希望现在任何浏览器都能够正确的设置Cache-Control 。 以下是我简要testing过的一个例子:

 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秒钟 – 你将不得不改变任何你想要的。 这种方法的优点是你可以为每个文件types指定不同的时间,甚至可以覆盖Cache-Control头的其他方面 – 你在这里讨论这个头,以及HTTP RFC的官方部分,如果你喜欢更多的东西正式。

第二种方法是安排那些会导致可caching内容的请求全部来自您可以在location指令中使用的特定path,如下所示:

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

这使得nginxconfiguration更容易,因为你可以使用它的builtin expires指令,但是这个选项是否非常依赖于你是否可以在你的代码上强制使用这种模式的URL。

截至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的map条目,它允许一个date值,或者甚至可以是application/pdf modified +42d例如

如果您必须使用MIMEtypes,请尝试:

 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; } 

我们在一个非常繁忙的网站上使用这个效果非常好。

$ sent_http_content_type无效。 请求标头值可以通过$ http_ name访问。 另外,对于Content-type头,nginx已经embedded了variables$ content_type。

如果你想检查$ content_type对一堆types,最好使用map:

  map $content_type $test_header { "text/css" OK; "text/html" OK; ... default ""; } server { location / { add_header "X-Test" $test_header; } } 

如果$ test_header计算为空string,则不会设置标题。

有关更多信息,请参阅: 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 /文档/ HTTP / ngx_http_headers_module.html#add_header