首页 > 解决方案 > 如何设置nginx仅在修改时传输静态文件

问题描述

我正在使用 nginx 来提供文件夹。我正在通过其他进程更改文件夹中的文件。我想以这样一种方式设置 nginx,即如果服务器上的文件未更改,则文件内容不会通过 http 发送。当文件改变时(即修改日期已经改变),文件被传输。我查看了一些文档并进行了一些谷歌搜索,但还没有找到适合这种情况的方法。大多数时候人们都在清除缓存文件夹,但这对我来说似乎不是很优雅。是否可以通过 304/200 代码进行组织?即,如果文件被更改,服务器将使用 HTTP 200 及其内容进行响应,否则使用 HTTP 304。

标签: httpnginxcachingbrowser-cache

解决方案


如何配置:

这已经是默认行为;为此,客户端必须根据ngx_http_not_modified_header_filter()http://nginx.org/r/if_modified_sinceIf-Modified-Since发送和/或If-None-Match ETag标头。


如何测试:

您可以通过查找给定资源的字段来轻松地使用curlLast-Modified进行测试,然后在标头中使用exact相同日期对相同资源发出后续请求(分别与相同)。If-Modified-SinceETagIf-None-Match


用于curl测试If-Modified-Since/ Last-Modified

%curl -i bmap.su | & fgrep -e Date -e HTTP -e Length -e Modified
HTTP/1.1 200 OK
Date: Sat, 10 Aug 2019 04:20:17 GMT
Content-Length: 12842
Last-Modified: Tue, 09 Apr 2013 17:18:16 GMT

%curl -i -H"If-Modified-Since: Tue, 09 Apr 2013 17:18:16 GMT" bmap.su | & fgrep -e Date -e HTTP -e Length -e Modified
HTTP/1.1 304 Not Modified
Date: Sat, 10 Aug 2019 04:20:41 GMT
Last-Modified: Tue, 09 Apr 2013 17:18:16 GMT

%curl -i -H"If-Modified-Since: Tue, 09 Apr 2013 17:18:17 GMT" bmap.su | & fgrep -e Date -e HTTP -e Length -e Modified
HTTP/1.1 200 OK
Date: Sat, 10 Aug 2019 04:27:47 GMT
Content-Length: 12842
Last-Modified: Tue, 09 Apr 2013 17:18:16 GMT

在上面的例子中:

  1. 我们首先查看Last-Modified资源的日期。

  2. 我们使用与先前响应标头中的日期相同If-Modified-Since的请求标头发出后续请求;请注意,我们得到了一个响应,正如缺少字段所期望的那样,它没有附带任何响应主体,从而节省了带宽。Last-Modified304 Not ModifiedContent-Length

  3. 我们最终测试了 nginx 对这个特性的默认设置;根据http://nginx.org/r/if_modified_sinceexact默认匹配;因此,如果我们提供了一个不准确的日期(无论是较早的还是较晚的),那么我们将返回200 OK一个完整的响应正文(这通常是您想要的,以避免在Last-Modified日期恢复时缓存中毒到更早的一个)。


用于curl测试If-None-Match/ ETag

%curl -i nginx.org | & fgrep -e HTTP/ -e Date: -e Server: -e Length: -e Modified: -e ETag:
HTTP/1.1 200 OK
Server: nginx/1.15.7
Date: Sat, 10 Aug 2019 05:24:06 GMT
Content-Length: 9053
Last-Modified: Tue, 23 Jul 2019 12:20:32 GMT
ETag: "5d36fb90-235d"

%curl -i -H "If-None-Match: 5d36fb90-235d" nginx.org | & fgrep -e HTTP/ -e Length: -e Modified: -e ETag:
HTTP/1.1 200 OK
Content-Length: 9053
Last-Modified: Tue, 23 Jul 2019 12:20:32 GMT
ETag: "5d36fb90-235d"

%curl -i -H 'If-None-Match: "5d36fb90-235d"' nginx.org | & fgrep -e HTTP/ -e Length: -e Modified: -e ETag:
HTTP/1.1 304 Not Modified
Last-Modified: Tue, 23 Jul 2019 12:20:32 GMT
ETag: "5d36fb90-235d"

这是我们在上面所做的:

  1. 第一步,我们通过ETag响应头请求查找实体标签;见https://en.wikipedia.org/wiki/HTTP_ETag

  2. 第二步,我们使用请求头ETag中提供的内容If-None-Match发出请求;请注意,我们忘记在它周围加上引号,这显然是强制性的,对于 nginx 和 Apache(可以很容易地根据 httpd.apache.org 主机进行验证)。

  3. 在第三步中,我们使用实际的If-None-Match请求标头发出正确的更正请求HTTP/1.1 304 Not Modified,并按预期接收带正文的响应。


推荐阅读