=== TEST 33: headers_sent & HEAD--- config location /lua { content_by_lua ' ngx.say(ngx.headers_sent) local ok, err = ngx.flush() if not ok then ngx.log(ngx.WARN, "failed to flush: ", err) return end ngx.say(ngx.headers_sent) '; }--- requestHEAD /lua--- response_body--- no_error_log[error]--- error_logfailed to flush: header only
=== TEST 34: HEAD & ngx.say--- config location /lua { content_by_lua ' ngx.send_headers() local ok, err = ngx.say(ngx.headers_sent) if not ok then ngx.log(ngx.WARN, "failed to say: ", err) return end '; }--- requestHEAD /lua--- response_body--- no_error_log[error]--- error_logfailed to say: header only
Hello!这里测试的点是 HTTP HEAD 请求。
Last-Modified
If-Modified-Since
Hello!麻烦提供一个最小化的例子吧,能供大家分析使用。
location /test/304 { content_by_lua_block { ngx.status = 200 ngx.header["ETag"] = "\"00f29033f37df21bf5e7d233f1387c67\"" ngx.header["Last-Modified"] = "Wed, 07 Nov 2018 02:34:43 GMT" ngx.log(ngx.DEBUG, ngx.print(123)) } }
curl -i -H "If-Modified-Since:Wed, 07 Nov 2018 02:34:43 GMT" localhost:7000/test/304HTTP/1.1 304 Not ModifiedServer: openresty/1.13.6.1Date: Wed, 07 Nov 2018 04:05:46 GMTConnection: keep-aliveETag: "00f29033f37df21bf5e7d233f1387c67"Last-Modified: Wed, 07 Nov 2018 02:34:43 GMT
因为是在生产环境中发现的,不确定client的request的详细参数,只知道request line是GET一个资源,属于下载业务,并且是从web浏览器发出的。目前详查了一下日志,发现最终给client的响应是304,所以我猜测request中带了“Last-Modified” 或者 “If-Modified-Since”。我又写了个case模拟这种情形,其他的都对上了,status由200自动变为304,没有body,就是ngx.print不出现错误。下面是一个实际业务请求非模拟case的流程图:在 2018年11月7日星期三 UTC+8上午10:34:24,tokers写道:Hello!麻烦提供一个最小化的例子吧,能供大家分析使用。
Hello!HTTP 协议里对 304 响应应该是说了不能携带 body 的。因此 nginx 的 ngx_http_header_filter_module 会设置 r->header_only = 1。ngx.print 会在如果头部没发送时先发送头部。在你这种情况下,ngx.print 内部发现发送完头部后 r->header_only = 1,然后就直接返回了。 ----这里的直接返回,就是说舍弃了上层传入的body??如果你再尝试用 ngx.print 发送一次数据,我相信就会出现 header only 的错误了。
Hello!不会。头部可以在使用 ngx.print/ngx.say 时隐式地被发送出去;也可以通过 ngx.send_headers 发送出去。