前言
大家都知道,nginx配置文件通过使用add_header指令来设置response header。
用curl查看一个站点的信息,发现返回的头部与想象中的不一样:
http/2 200 date: thu, 07 feb 2019 04:26:38 gmt content-type: text/html; charset=utf-8 vary: accept-encoding, cookie cache-control: max-age=3, must-revalidate last-modified: thu, 07 feb 2019 03:54:54 gmt x-cache: miss server: cloudflare ...
主站点在nginx.conf中配置了hsts等header:
add_header strict-transport-security "max-age=63072000; preload"; add_header x-frame-options sameorigin; add_header x-content-type-options nosniff; add_header x-xss-protection "1; mode=block";
但响应头部没有这些header。除了常规的header,仅出现了一个配置配置在location中的header x-cache。
第一印象是cdn过滤了这些header?于是找cloudflare的文档,没发现会对这些进行处理。转念一想,cdn过滤这些干啥啊?吃饱了撑的啊?他们又不搞zheng审那一套!
问题转移到nginx的配置上。打开google搜索”nginx location add_header”,果然发现不少槽点。点开官网add_header的文档,有这样的描述(其他信息已省略):
there could be several add_header directives. these directives are inherited from the previous level if and only if there are no add_header directives defined on the current level.
注意重点在“these directives are inherited from the previous level if and only if there are no add_header directives defined on the current level. ”。即:仅当当前层级中没有add_header指令才会继承父级设置。所以我的疑问就清晰了:location中有add_header,nginx.conf中的配置被丢弃了。
这是nginx的故意行为,说不上是bug或坑。但深入体会这句话,会发现更有意思的现象:仅最近一处的add_header起作用。http、server和location三处均可配置add_header,但起作用的是最接近的配置,往上的配置都会失效。
但问题还不仅于此。如果location中rewrite到另一个location,最后结果仅出现第二个的header。例如:
location /foo1 { add_header foo1 1; rewrite / /foo2; } location /foo2 { add_header foo2 1; return 200 "ok"; }
不管请求/foo1还是/foo2,最终header只有foo2:
尽管说得通这是正常行为,但总让人感觉有点勉强和不舒坦:server丢掉http配置,location丢掉server配置也就算了,但两个location在同一层级啊!
不能继承父级配置,又不想在当前块重复指令,解决办法可以用include指令。
以上是Nginx的add_header指令实例分析的详细内容。更多信息请关注PHP中文网其他相关文章!